2017-03-07 73 views
1

說我們有一個類Foo定義如下:爲什麼傳遞shared_from_this()會導致段錯誤?

// foo.hpp 
class Foo; 

using FooCallback = std::function<void(std::shared_ptr<Foo> ins)>; 

class Foo : public std::enable_shared_from_this<Foo>{ 
public: 
    Foo(int b, const FooCallback& callback):m_bar(b), 
              m_callback(callback){} 

    int 
    getBar(); 

    void 
    doSth(); 

private: 
    int m_bar; 
    const FooCallback& m_callback; 
}; 

爲什麼將下面的代碼段造成的故障?

// foo.cpp 
#include "foo.hpp" 

int 
Foo::getBar(){ 
    return m_bar; 
} 

void 
Foo::doSth(){ 
    std::cout << "Start ... " << std::endl; 
    this->m_callback(shared_from_this()); 
    std::cout << "End ... " << std::endl; 
} 

int main() 
{ 
    auto f = std::make_shared<Foo>(100, 
     [](std::shared_ptr<Foo> ins){ 
      std::cout << "bar: " << ins->getBar() << std::endl; 
     }); 
    f->doSth(); 
    return 0; 
} 

輸出是:

開始......

分段故障

據我瞭解,這是怎麼回事:

  1. 在main()中,f是指向Foo實例的shared_ptr,說它是ins
  2. 調用f->doSth()時,實際調用ins.doSth()
  3. 在ins.doSth中,this是指向ins的指針。 shared_from_this()是一個shared_ptr到ins

那麼爲什麼步驟3導致段錯誤?

回答

2

這與shared_from_this無關。如果您查看調試器,則會顯示此段錯誤位於std::function的內部指針指向的位置。

發生這種情況是因爲m_callback是引用,並且當您調用doSth(因爲它是臨時對象)時,它所引用的函數對象不再存在。

爲了解決這個問題,你可以通過值保存m_callback

const FooCallback m_callback; 

甚至更​​好,因爲在lambda不捕獲任何東西,你可以做m_callback一個純函數引用(或指針):

using FooCallback = void(std::shared_ptr<Foo> ins); 

… 

    FooCallback& m_callback; 

… 

auto f = std::make_shared<Foo>(100, 
     *[](std::shared_ptr<Foo> ins){ 
      std::cout << "bar: " << ins->getBar() << std::endl; 
     }); 
+0

非常感謝。我發現這些概念真的很混亂。我知道也許我不應該問這個問題,但是請給我推薦一些關於學習現代C++的知識? – stupidlearner

+1

我還沒有讀過任何C++書籍,所以我不能親自推薦任何內容,只需檢查[this](http://stackoverflow.com/q/388242/3425536)。 – emlai

相關問題