2
#include <functional>
#include <iostream>

using namespace std;

class test {
public:
  test(){ p = new int[10];}
 void print_info(double a)
  {
    cerr << a << endl;
  }
  ~test(){
    cerr << __LINE__ << endl;
    delete []p;
  }
private:
  int *p;
};

int main()
{
    test t;
    std::function<void(void)> f = std::bind(&test::print_info, t, 2.0);
    //std::function<void(void)> f = std::bind(&test::print_info, std::cref(t), 2.0);
    return 0;
}

test::~test()が 2 回呼び出されるため、クラッシュします。ただし、 (or ) に置き換えるtと、 main() を終了するときに 1 回だけ呼び出されます。std::cref(t)std::ref(t), &t~test()

理由がわかりませんでした。gcc 4.6.3を使用して、Ubuntu 12.04 64ビットを使用しています。

4

3 に答える 3

4

copy of object tそれ自体ではなくa をバインドしているため、オブジェクトtから戻るときにbind破壊され、コピー c-tor をオーバーロードしないため、デフォルトのコピー c-tor は浅いコピーを作成し、あなたpは 2 回削除されます。バインディングt自体には、 を使用する必要がありますstd::ref

于 2013-11-08T12:39:23.140 に答える
0
std::function<void(void)> f = std::bind(&test::print_info, t, 2.0);

test::~test() が 2 回呼び出されるため、クラッシュします。しかし、t を std::cref(t) (または std::ref(t), &t) に置き換えると、main() を終了するときに ~test() が 1 回だけ呼び出されます。

理由がわかりませんでした。gcc 4.6.3を使用して、Ubuntu 12.04 64ビットを使用しています。

理由は実際には非常に単純です。関数は、引数のコピーstd::bindを保持するファンクター オブジェクトを作成します。あなたのプログラムにはバグがあり、型のオブジェクトをコピーすると、同じメモリへのポインターを持ち、両方がデストラクタを呼び出す 2 つのオブジェクトになってしまいます。delete[]

バインドすると、オブジェクト&tアドレス(ポインタ) がコピーされます。2 つの別個のオブジェクトはなく、1 つのオブジェクトとポインターだけです。同様に、ユーティリティstd::refstd::cref参照ラッパーです。つまり、別のオブジェクトをラップし、参照のようなセマンティクスを提供するオブジェクトです。何度std::refコピーしても、すべてのコピーは同じオブジェクトへの参照として動作します。オブジェクト自体がコピーされることはありません。

于 2013-11-08T13:59:30.360 に答える