我遇到了这个问题,但我不知道该怎么做...
class Goo
{
char _ch;
string _str;
public:
function<void(void)> dobedo;
// Constructor 1
Goo(string s) : _str(s)
{
cout << "Constructed: [" << &_str << "]: " << _str << endl;
dobedo = [&]()
{
cout << "Dobedo: [" << &_str << "]: "<< _str << endl;
};
}
// Constructor 2
Goo(char ch) : _ch(ch)
{
dobedo = [&]() {
cout << "Dobedo: " << _ch << endl;
};
}
void show() { cout << "Show: [" << &_str << "]: " << _str << endl; }
};
int main()
{
string myStr1("ABCD");
string myStr2("EFGH");
vector<Goo> goos;
goos.push_back(Goo(myStr1));
goos.push_back(Goo(myStr2));
goos[0].dobedo();
goos[1].dobedo();
goos[0].show();
goos[1].show();
return 0;
}
由于某些原因,尽管能够找到内存地址,但函数对象无法打印_str:
Constructed: [00EFF80C]: ABCD
Constructed: [00EFF7B0]: EFGH
Dobedo: [00EFF80C]:
Dobedo: [00EFF7B0]:
Show: [032F2924]: ABCD
Show: [032F296C]: EFGH
虽然我对char变量没有任何问题。
int main()
{
vector<Goo> goos;
goos.push_back(Goo('#'));
goos.push_back(Goo('%'));
goos[0].dobedo();
goos[1].dobedo();
return 0;
}
输出结果为:
Dobedo: #
Dobedo: %
有什么想法吗?
答案 0 :(得分:3)
您在代码中有未定义的行为而没有定义复制构造函数。默认复制构造函数按值复制所有成员。所以你的lambda对象被复制并保存对被破坏对象的引用 - _str
(当调用push_back
方法时必须重新分配vector时)。
定义复制构造函数并移动Goo
类的构造函数:
Goo(const Goo& g)
{
_str = g._str;
dobedo = [&]()
{
cout << "Dobedo: [" << &_str << "]: "<< _str << endl;
};
}
Goo(Goo&& g)
{
_str = move(g._str);
dobedo = [&]()
{
cout << "Dobedo: [" << &_str << "]: "<< _str << endl;
};
}
答案 1 :(得分:1)
您的输出清楚地显示构造函数中_str
的地址与show
中的地址不同。这意味着您的对象已被复制/移动。它可能会在被推送到矢量时发生。顺便说一下,当你向矢量推送/弹出其他元素时也可能发生这种情况,因为矢量不能保证元素保持在同一个存储器地址。
创建dobedo
仿函数时,会将所有捕获的字段复制到其中。在第一种情况下,_str
的地址在复制/移动对象时变为无效(没有人在移动/复制时更新它!)。偶尔我们可能会在该地址找到类似空字符串的东西(尽管访问它现在是一个内存违规)。在第二种情况下,捕获并存储一个字符 - 它肯定在任何对象位置更改时仍然有效。