2017-03-07 74 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

相关问题