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



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

#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;
}

输出:

constructor: 4
destructor: 4
Value is: 4
Value is: 4
destructor: 4

此输出是否正确?

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

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

  • 原始临时 lambda 的Instance成员;

  • 存储在std::function中并一直存在到main年底的 lambda 副本的Instance成员。

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

修订后的代码:

#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

最新更新