gpt4 book ai didi

c++ - 仍在执行时调用 std::function 析构函数

转载 作者:搜寻专家 更新时间:2023-10-31 02:03:53 25 4
gpt4 key购买 nike

我想动态地改变一个类的方法的行为,所以我实现了这些方法调用 std::functionoperator() 持有一个拷贝一个 lambda 函数,一次依赖于一些只有在类构造之后才知道的值。lambda 改变了类的状态,因此它们重置了一个包含所有动态方法行为的容器。
执行上面的想法我在重置容器后无法访问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;
}

产生输出:

From capture list, before: hello
From arg, before: hello
From capture list, after:
From arg, after: hello

variableValuevector 干净后失效。

捕获列表失效是预期结果吗?在调用 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);
}

函数参数很好,因为它是一个拷贝,但是在 delete this 之后,成员 Foo::variableValue 不再存在,所以你的程序有未定义的行为试图使用它。

常识是continuing to run the function itself is legal (因为函数定义不是对象,不能“删除”;它们只是程序的一个基本属性),只要您足够好地保留封装类的成员即可。

不过,除非您确实需要,否则我建议您避免使用这种模式。人们很容易混淆你的类的所有权责任(即使“你的类”是从 lambda 表达式自动生成的!)。


Is the capture list invalidation an expected result?

是的。

Is safe using any other local variable, not only in the capture list, after calling std::function destructor?

是的。

Is there a suggested way / pattern to accomplish the same behaviour in a safer way (excluding huge switches/if on class states)?

如果不了解您正在尝试做的事情,就不可能肯定地说。但是您可以尝试将 shared_ptr 存储在您的 vector 中……注意不要在 lambda 本身中捕获 shared_ptr,否则它永远不会 清理干净!捕获一个 weak_ptr 可能对此有好处;它可以“转换”为 lambda 主体内的 shared_ptr,这将在所述主体的持续时间内保护 lambda 的生命。

关于c++ - 仍在执行时调用 std::function 析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54647441/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com