C++ 在lambda捕获说明符内声明的类实例上运行两次析构函数

C++ 在lambda捕获说明符内声明的类实例上运行两次析构函数,c++,lambda,c++14,C++,Lambda,C++14,运行以下代码时,析构函数似乎运行了两次。我有一个理论,这可能与添加自动移动构造函数有关,但我不确定如何测试它 #include <iostream> #include <functional> struct Structure { Structure(int n) : Value(n) { std::cout << "constructor: " << Value << std::endl; }

运行以下代码时,析构函数似乎运行了两次。我有一个理论,这可能与添加自动移动构造函数有关,但我不确定如何测试它

#include <iostream>
#include <functional>

struct Structure {
   Structure(int n) :
      Value(n) {
      std::cout << "constructor: " << Value << std::endl;
   }
   ~Structure() {
      std::cout << "destructor: " << Value << std::endl;
   }
   int Value;
};

int main() {
   int Init = 4;
   std::function<void()> Function = [Instance = Structure(Init)] () {
      std::cout << "Value is: " << Instance.Value << std::endl;
   };
   Function();
   Function();
   return 0;
}

此输出正确吗?

std::function
通过复制您提供的可调用对象来工作。这里没有复制省略,因为lambda不是
std::function
,而是匿名的、不相关的类型

因此,您看到的两个析构函数是:

  • 原始、临时lambda的
    实例
    成员

  • lambda副本的
    实例
    成员,该lambda存储在
    std::function
    中并一直存在到
    main
    结束


好的,我手动定义了move和copy构造函数,当我指示编译器在下面代码的变体中删除它们时,也看到了错误。一切似乎都很正常

修订守则:

#include <iostream>
#include <functional>

struct Structure {
   Structure(int n) :
      Value(n) {
      std::cout << "constructor: " << Value << std::endl;
   }

   Structure(const Structure& other) :
      Value(other.Value) {
      std::cout << "copy constructor: " << Value << std::endl;
   }

   Structure(Structure&& other) :
      Value(other.Value) {
      other.Value = -1;
      std::cout << "move constructor: " << Value << std::endl;
   }

   ~Structure() {
      std::cout << "destructor: " << Value << std::endl;
   }
   int Value;
};

int main() {
   int Init = 4;
   std::function<void()> Function = [Instance = Structure(Init)] () {
      std::cout << "Value is: " << Instance.Value << std::endl;
   };
   Function();
   Function();
   return 0;
}

因此,当您创建自己的复制构造函数和移动构造函数并在其中放置断点时;这是对“我有一个理论,这可能与添加自动移动构造函数有关,但我不确定如何测试它;有什么建议?”的回答,我觉得这是一个比“我是对的”好得多的问题?
#include <iostream>
#include <functional>

struct Structure {
   Structure(int n) :
      Value(n) {
      std::cout << "constructor: " << Value << std::endl;
   }

   Structure(const Structure& other) :
      Value(other.Value) {
      std::cout << "copy constructor: " << Value << std::endl;
   }

   Structure(Structure&& other) :
      Value(other.Value) {
      other.Value = -1;
      std::cout << "move constructor: " << Value << std::endl;
   }

   ~Structure() {
      std::cout << "destructor: " << Value << std::endl;
   }
   int Value;
};

int main() {
   int Init = 4;
   std::function<void()> Function = [Instance = Structure(Init)] () {
      std::cout << "Value is: " << Instance.Value << std::endl;
   };
   Function();
   Function();
   return 0;
}
constructor: 4
move constructor: 4
destructor: -1
Value is: 4
Value is: 4
destructor: 4