2017-03-07 15 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では、thisinsへのポインタです。 shared_from_this()insのshared_ptrです。

なぜ、ステップ3でセグメント障害が発生していますか?

答えて

2

これは、shared_from_thisとは関係ありません。デバッガを見ると、std::functionの内部ポインタが指し示している場所でこのエラーが発生していることがわかります。

doSth(一時オブジェクトであるため)を呼び出すと、m_callbackが参照であり、参照する関数オブジェクトがもう存在しないために発生します。あなたは値によってm_callbackを保存することができます。この問題を解決するには

:ラムダは何をキャプチャしていないので、あなたがm_callbackプレーンな関数参照(またはポインタ)を作ることができ、

const FooCallback 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

関連する問題