Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在仍然执行std::function析构函数时调用它_C++_C++11 - Fatal编程技术网

C++ 在仍然执行std::function析构函数时调用它

C++ 在仍然执行std::function析构函数时调用它,c++,c++11,C++,C++11,我想动态地改变一个类的方法的行为,所以我实现了这些方法,调用一个std::函数的操作符(),该函数包含一个lambda函数的副本,这取决于一次仅在类构造之后才知道的一些值。 lambda会更改类的状态,因此它们会重置包含所有动态方法行为的容器。 执行上述想法时,在重置容器后,我无法访问lamba的捕获列表。 以下代码段再现了该问题: std::vector< std::function<void(std::string)> > vector; int main() {

我想动态地改变一个类的方法的行为,所以我实现了这些方法,调用一个std::函数的操作符(),该函数包含一个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;
}
其中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);
}