C++ 在仍然执行std::function析构函数时调用它
我想动态地改变一个类的方法的行为,所以我实现了这些方法,调用一个std::函数的操作符(),该函数包含一个lambda函数的副本,这取决于一次仅在类构造之后才知道的一些值。 lambda会更改类的状态,因此它们会重置包含所有动态方法行为的容器。C++ 在仍然执行std::function析构函数时调用它,c++,c++11,C++,C++11,我想动态地改变一个类的方法的行为,所以我实现了这些方法,调用一个std::函数的操作符(),该函数包含一个lambda函数的副本,这取决于一次仅在类构造之后才知道的一些值。 lambda会更改类的状态,因此它们会重置包含所有动态方法行为的容器。 执行上述想法时,在重置容器后,我无法访问lamba的捕获列表。 以下代码段再现了该问题: std::vector< std::function<void(std::string)> > vector; int main() {
执行上述想法时,在重置容器后,我无法访问lamba的捕获列表。
以下代码段再现了该问题:
std::vector< std::function<void(std::string)> > vector;
int main() {
//Change class state when variable value will be known
std::string variableValue = "hello";
auto function = [variableValue](std::string arg) {
std::cout <<"From capture list, before: "<< variableValue << std::endl;
std::cout <<"From arg, before: " << arg << std::endl;
vector.clear();
std::cout << "From capture list, after: " << variableValue << std::endl;
std::cout << "From arg, after: " << arg << std::endl;
};
vector.push_back(function);
//Dynamic method execution
vector[0](variableValue);
return 0;
}
其中variableValue在向量清除后无效
捕获列表无效是否为预期结果?
在调用std::function destructor之后,使用任何其他局部变量(不仅在捕获列表中)是否安全?
是否有建议的方法/模式以更安全的方式实现相同的行为(不包括大型开关/if on类状态)?,其中
在您的例子中,目标是一个lambda表达式。使用lambda表达式时,编译器将生成一个
执行vector.clear()
时,其元素的析构函数将运行,因此闭包的captures by value的析构函数(成员变量)将运行
至于引用的捕获
因此,在std::function
的析构函数运行之后,通过值和引用访问任何捕获都是不安全的
实际的
操作符()
如何?所以他们没有。因此,只要不访问任何捕获,只要在析构函数运行后执行操作符()。请参阅。对于这个问题,我们可以去掉std::function
、lambda和vector。由于lambda只是带有函数调用运算符的类的语法糖,因此您的测试用例实际上与此相同:
struct Foo
{
std::string variableValue = "hello";
void bar(std::string arg)
{
std::cout <<"From capture list, before: "<< variableValue << std::endl;
std::cout <<"From arg, before: " << arg << std::endl;
delete this; // ugrh
std::cout << "From capture list, after: " << variableValue << std::endl;
std::cout << "From arg, after: " << arg << std::endl;
}
};
int main()
{
Foo* ptr = new Foo();
ptr->bar(variableValue);
}
structfoo
{
std::string variableValue=“hello”;
空栏(标准::字符串参数)
{
std::cout捕获列表无效是预期结果吗?
因为捕获存储在类的成员中,是的。那么“代码本身”呢?std::函数的代码在调用其析构函数时是否以某种方式被“销毁”?或者只要不访问类的内存,代码就可以毫无问题地运行(作为捕获列表的结果存储的成员)?代码本身位于二进制文件的文本
部分,它不是动态分配的。这与询问是否可以在成员函数中安全合法地删除*此
,只要以后不引用任何成员是一样的(当然,代码< >删除>这个< /代码>是非常邪恶的!)-一般的共识是“是”,但是引用这个效果会完成你的答案。@ ListNeasraceSimRealSoad谢谢,我添加了一个链接到C++链接,你的链接链接到。非常感谢你的宝贵答案。我也很欣赏SyrdYPPTR上的提示。
struct Foo
{
std::string variableValue = "hello";
void bar(std::string arg)
{
std::cout <<"From capture list, before: "<< variableValue << std::endl;
std::cout <<"From arg, before: " << arg << std::endl;
delete this; // ugrh
std::cout << "From capture list, after: " << variableValue << std::endl;
std::cout << "From arg, after: " << arg << std::endl;
}
};
int main()
{
Foo* ptr = new Foo();
ptr->bar(variableValue);
}