C++ 使用std::function作为成员函数,它捕获'this',并在析构函数之后从复制的lambda访问它
发布一个代码示例(我认为它是最小的、完整的和可验证的足够了):C++ 使用std::function作为成员函数,它捕获'this',并在析构函数之后从复制的lambda访问它,c++,lambda,temporary-objects,C++,Lambda,Temporary Objects,发布一个代码示例(我认为它是最小的、完整的和可验证的足够了): 为什么??背后是什么 如何修复?(输出100500,而不是-1) 我在询问框中写了一些我自己的理由,但发现它更适合作为答案发布(这会使问题太长)。如果我的答案是错误的,请更正它,欢迎更多的答案啊,它应该责怪临时-Bang(100500)的析构函数,它返回表单GetBang,is,have ,例如: 因为这里是noRVO,所以临时Bang(100500)将首先分配给b,然后被销毁 customoperator()、constr
- 为什么??背后是什么
- 如何修复?(输出
,而不是100500
)-1
我在
询问框中写了一些我自己的理由,但发现它更适合作为答案发布(这会使问题太长)。如果我的答案是错误的,请更正它,欢迎更多的答案啊,它应该责怪临时-Bang(100500)
的析构函数,它返回表单GetBang
,is,have
,例如:
因为这里是noRVO
,所以临时Bang(100500)
将首先分配给b
,然后被销毁
customoperator()
、constructor
和destructor
以输出一些信息:
显示:
dtor
将在输出之前被调用,这意味着临时对象已被销毁李>
m_值
的地址不变李>
这两个参数保证我们仍然可以从b
的m\u foo()
访问临时变量的m\u值
访问已销毁的对象时,应该是未定义的行为,但不需要警告和错误
更新
要解决此问题,有两种解决方案:
正如前面指出的,使用初始值设定项捕获:[bang=*this]
。这需要c++14
通过复制捕获当前对象更简单的方法:[*this]
。这需要c++17李>
您可能希望通过值*将当前对象传递给lambda,以便在复制assignBang
时可以存储和复制该对象。传递指针此
将存储并复制指向临时对象的指针,该临时对象在复制assignBang
时已被销毁
这是应该做到的:
#include <iostream>
#include <functional>
class Bang
{
public:
Bang(int i = 0) : m_val(i)
{
m_foo = [bang = *this] { std::cout << bang.m_val << std::endl; };
}
~Bang()
{
m_val = -1;
}
void Foo()
{
m_foo();
}
private:
int m_val;
std::function<void()> m_foo;
};
Bang GetBang()
{
return Bang(100500);
}
int main()
{
Bang b;
b = GetBang();
b.Foo();
return 0;
}
#包括
#包括
课堂爆炸
{
公众:
Bang(int i=0):m_val(i)
{
m_foo=[bang=*this]{std::cout
-1
class Lambda
{
public:
void operator()() const
{
//output
}
private:
Bang& bang;
public:
Lambda(Bang& bang) : bang{bang}
{
}
} lambda{*this};
...
m_foo = lambda;
#include <iostream>
#include <functional>
using namespace std;
class Bang
{
public:
Bang(int i = 0) : m_val(i)
{
std::cout << "Bang(int i = 0) m_val address is " << &m_val << '\n';
class Lambda
{
public:
void operator()() const
{
std::cout << "operator() m_val address is " << &bang.m_val << '\n';
std::cout << bang.m_val << std::endl;
}
private:
Bang &bang;
public:
Lambda(Bang &bang) : bang{bang}
{
}
} lambda{*this};
m_foo = lambda;
}
~Bang()
{
std::cout << "~Bang()\n";
m_val = -1;
}
void Foo()
{
m_foo();
}
private:
int m_val;
std::function<void()> m_foo;
};
Bang GetBang()
{
return Bang(100500);
}
int main()
{
Bang b;
b = GetBang();
b.Foo();
return 0;
}
Bang(int i = 0) m_val address is 0x7ffd202c48b0
Bang(int i = 0) m_val address is 0x7ffd202c48e0
~Bang()
operator() m_val address is 0x7ffd202c48e0
-1
~Bang()
#include <iostream>
#include <functional>
class Bang
{
public:
Bang(int i = 0) : m_val(i)
{
m_foo = [bang = *this] { std::cout << bang.m_val << std::endl; };
}
~Bang()
{
m_val = -1;
}
void Foo()
{
m_foo();
}
private:
int m_val;
std::function<void()> m_foo;
};
Bang GetBang()
{
return Bang(100500);
}
int main()
{
Bang b;
b = GetBang();
b.Foo();
return 0;
}