0

次のコードがセグメンテーション違反になる理由はありますか?

class foo任意のクラスを表します。これは、イベント化されたインターフェイスを提供するための良いアイデアのようです。

#include <iostream>
#include <functional>

class foo
{
public:
  foo()
  {
    val = 42;  
  };

  void bar(std::function<int(foo*)> f)
  {
    this->_bar = std::bind(f, this);
  }
  std::function<int()> _bar;
  int val;
};

int main(void)
{
  foo *foobar;
  foobar->bar([](foo *self)->int{return self->val;});

  std::cout << foobar->_bar();
}
4

4 に答える 4

6

foobarは何も指していないため、セグメンテーション違反になります。使用する必要がありますfoo foobar;

編集:

簡単なレビュー。

class foo
{
public:
  foo()
  {
    val = 42;  // Use initialization list.
  };

  void bar(std::function<int(foo*)> f) // Use reference (foo&) instead of pointer (foo*).
  {
    this->_bar = std::bind(f, this); // Move "f" into bind and use "std::ref()" so you can pass "*this" by reference without copying.
  }

  // Hide local member variables

  std::function<int()> _bar; // Never use _ as a prefix, only the compiler is allowed to use _ prefix.
  int val;
};

int main(void)
{
  foo *foobar; // Use value semantics, i.e. "foo foobar".

  foobar->bar([](foo *self)->int{return self->val;});

  std::cout << foobar->_bar();
}

例えば

class foo
{
public:
    foo()
        : val_(42)
    {
    };

    void set_bar(std::function<int(foo&)> f)
    {
        bar_ = std::bind(std::move(f), std::ref(*this));
    }

    int invoke_bar() const
    {   
        return bar_;
    }

    int get_val() const
    {
        return val_;
    }

private:

    std::function<int()> bar_;
    int val_;
};

int main(void)
{
  foo foobar;
  foobar.set_bar([](foo& self) -> int
  {
     return self.get_val();
  });

  std::cout << foobar.invoke_bar();
}
于 2012-12-26T10:59:41.420 に答える
3

foo を作成することはありません。それへのポインターを宣言するだけです。に変更foo* foobarfoo foobar、 でアドレスを取得します&。(この例では必要ありません)。

これはうまくいくはずです。

foo foobar;
foobar.bar([](foo* self){return self->val;});
std::cout << foobar._bar() << std::endl;
return 0;
于 2012-12-26T11:00:16.627 に答える
2

newfoob​​ar ポインターを宣言しましたが、それにメモリを割り当てるために使用しなかったためです。foo *foobar = new foo();コードが機能するはずです。ただし、自動保存期間も使用し、パラメーターを参照によってラムダに渡します。

int main(void)
{
  foo foobar;
  foobar.bar([](foo *self)->int{return self->val;});

  std::cout << foobar._bar();
}
于 2012-12-26T10:59:23.153 に答える
1

誰も明示的に言っているようには見えないので、あなたの問題はラムダとは何の関係もありません。通常の機能オブジェクト、または即時の関数呼び出しでまったく同じ問題が発生します。ラムダやその他の「高度な」機能について心配する前に、言語の基本を学ぶ必要があります。この場合:

  1. 初期化されていない変数を使用することはできません。ポインターを使用した場合の結果は、通常、 uninitialized を使用した場合よりも目を見張るものがありますがint、すべての場合において未定義の動作です。変数にクラス型がある場合は、すべてのメンバー (および基本クラス) を初期化するコンストラクターを定義します。変数にクラス型がない場合 (およびポインターにクラス型がない場合)は、初期化句なしで定義しないでください。

  2. C++ はデフォルトで値セマンティクスを使用します。正当な理由がない限り、ポインターを使用しないでください。値を使用します。

bindandを使用せずにこれらの原則を尊重するコードを記述できるようになるまで、 andlambdaを見ないでください。歩き方を知るまでは走れない。bindlambda

于 2012-12-26T11:41:37.993 に答える