【发布时间】:2014-12-08 02:18:59
【问题描述】:
我已将代码简化为仍然存在问题的最小示例。此代码应打印“42”,而是打印不同的数字。我还在析构函数中打印了“秘密”对象的地址,当它被访问时,表明它被过早地破坏了。我在这里做错了什么,还是编译器有问题?
代码:
#include <iostream>
using namespace std;
struct Secret{
int value;
Secret(int value):value(value){}
~Secret(){
cout<<"destructor:"<<(void*)this<<endl;
value=0;
}
};
template<class Func>
class Copier{
public:
Func func;
Copier(Func func):func(func){}
void run(){
func();
}
auto copy(){
auto output = [this](){
func();
};
Copier<decltype(output)> out(output);
return out;
}
};
auto makeSecretPrinter(){
Secret secret(42);
auto secretPrinter = [secret](){
cout<<"reading object at address:"<<(void*)&secret<<endl;
cout<<"the secret is:"<<secret.value<<endl;
};
return Copier<decltype(secretPrinter)>(secretPrinter).copy();
}
int main(){
makeSecretPrinter().run();
return 0;
}
clang(版本 3.5-1ubuntu1)输出:
destructor:0x7fff9e3f9940
destructor:0x7fff9e3f9938
destructor:0x7fff9e3f9948
destructor:0x7fff9e3f9950
reading object at address:0x7fff9e3f9940
the secret is:0
GCC (Ubuntu 4.9.2-0ubuntu1~14.04) 4.9.2 输出:
destructor:0x7fff374facc0
destructor:0x7fff374facb0
destructor:0x7fff374faca0
destructor:0x7fff374fac90
reading object at address:0x7fff374facc0
the secret is:-1711045632
【问题讨论】:
-
捕获
this意味着用指针语义捕获。如果捕获的对象被销毁,您可能不会取消引用该指针(甚至不能隐式取消引用,就像在copy的outputlambda 中所做的那样)。复制该 lambda 会复制捕获的指针,即执行浅拷贝。 -
auto output = [this](){这行似乎是问题所在。你真的想复制*this而不是指针 -
@BryanChen 跟我想的一模一样:coliru.stacked-crooked.com/a/43b70f00c4a20469
-
感谢@BryanChen,我没有意识到可以在 lambda 中捕获 *this。效果很好!
-
程序有问题。请参阅下面的答案