如果 std::variant 的析构函数包含 void* 数据,它会做什么
What will destructor of a std::variant do if it contains void* data
我刚刚开始在我的项目中使用 std::variant
。我有个疑问。 std::variant
的析构函数在下面显示的代码中会做什么。 Variant 持有一个 void*
数据。一旦 variant 超出范围,我认为它只会释放 void*
的内存,而不是指针指向的实际对象。所以这种情况下会出现内存泄漏。我想知道我的理解是否正确。
#include <iostream>
#include <memory>
#include <variant>
using namespace std;
class A {
public:
~A(){
cout<<"Destructor called"<<endl;
}
};
int main() {
std::variant<void*> data;
A* b = new A();
data = (void*)b;
return 0;
}
你是对的。标准库中唯一拥有 类 且实际对指针执行 delete
(或 delete[]
)的指针是智能指针。
std::variant
应该支持您保存任意数量类型的一个对象,主要不是指向对象的指针。如果变体包含指针,则意味着其他某个对象拥有该数据并负责删除它。
只能容纳一种类型的std::variant
也很少有用。在这种情况下,您可以将该变量声明为该类型的普通变量。
这是一个使用 std::variant
能够容纳两种不相关类型的对象的示例,破坏将按预期发生。
#include <iostream>
#include <variant>
class A {
public:
~A() { std::cout << "A destructor called\n"; }
};
class B {
public:
B() {}
B(const B&) = default;
B& operator=(const B&) = default;
~B() { std::cout << "B destructor called\n"; }
};
int main() {
std::variant<A, B> data; // now holds a default constructed A
data = B(); // deletes the A and now holds a default constructed B
std::cout << "---\n";
}
输出:
A destructor called // in "data = B()", the A must be destroyed
B destructor called // the temporary B used in "data = B()"
---
B destructor called // the B in the variant when the variant goes out of scope
当变体析构函数触发时,它将为此时存储在变体中的任何类型的项目调用析构函数。如果那是一个 void*
,那么 C++ 会说“好吧,我会清理 void*
,因为这是一个基本类型,所以这是一个空操作。”它不会查看 void*
,意识到它实际上是指向 A
的指针,然后 delete
指针就好像它是 A*
.
评论指出使用 void*
的变体是相当不寻常的。 void*
表示“我指着某物,作为用户,由你来跟踪它是什么并进行适当的转换和资源管理。”变体意味着“我持有以下实际事物之一,我希望 C++ 记住哪一个并为我进行适当的资源管理。”您可能需要重新考虑您的设计,因为这里可能有更简单的方法来完成您的目标。
我刚刚开始在我的项目中使用 std::variant
。我有个疑问。 std::variant
的析构函数在下面显示的代码中会做什么。 Variant 持有一个 void*
数据。一旦 variant 超出范围,我认为它只会释放 void*
的内存,而不是指针指向的实际对象。所以这种情况下会出现内存泄漏。我想知道我的理解是否正确。
#include <iostream>
#include <memory>
#include <variant>
using namespace std;
class A {
public:
~A(){
cout<<"Destructor called"<<endl;
}
};
int main() {
std::variant<void*> data;
A* b = new A();
data = (void*)b;
return 0;
}
你是对的。标准库中唯一拥有 类 且实际对指针执行 delete
(或 delete[]
)的指针是智能指针。
std::variant
应该支持您保存任意数量类型的一个对象,主要不是指向对象的指针。如果变体包含指针,则意味着其他某个对象拥有该数据并负责删除它。
只能容纳一种类型的std::variant
也很少有用。在这种情况下,您可以将该变量声明为该类型的普通变量。
这是一个使用 std::variant
能够容纳两种不相关类型的对象的示例,破坏将按预期发生。
#include <iostream>
#include <variant>
class A {
public:
~A() { std::cout << "A destructor called\n"; }
};
class B {
public:
B() {}
B(const B&) = default;
B& operator=(const B&) = default;
~B() { std::cout << "B destructor called\n"; }
};
int main() {
std::variant<A, B> data; // now holds a default constructed A
data = B(); // deletes the A and now holds a default constructed B
std::cout << "---\n";
}
输出:
A destructor called // in "data = B()", the A must be destroyed
B destructor called // the temporary B used in "data = B()"
---
B destructor called // the B in the variant when the variant goes out of scope
当变体析构函数触发时,它将为此时存储在变体中的任何类型的项目调用析构函数。如果那是一个 void*
,那么 C++ 会说“好吧,我会清理 void*
,因为这是一个基本类型,所以这是一个空操作。”它不会查看 void*
,意识到它实际上是指向 A
的指针,然后 delete
指针就好像它是 A*
.
评论指出使用 void*
的变体是相当不寻常的。 void*
表示“我指着某物,作为用户,由你来跟踪它是什么并进行适当的转换和资源管理。”变体意味着“我持有以下实际事物之一,我希望 C++ 记住哪一个并为我进行适当的资源管理。”您可能需要重新考虑您的设计,因为这里可能有更简单的方法来完成您的目标。