如何阻止在堆栈分配的对象上调用析构函数?
How to stop a destructor from being called on a stack allocated object?
我有一个类似 union 的 class,其成员可能是也可能不是垃圾,具体取决于也在同一 class 中设置的布尔标志。
显然,当我的 class 超出范围时,我不希望这些垃圾被销毁。如何防止 class 成员被破坏?
我知道这可以通过指针和动态分配的内存来实现,但我正在寻找更简单的解决方案。
class MyContainer {
bool has_child;
MyChild child;
public:
MyContainer(MyChild child) { this->has_child = true; this->child = child; }
MyContainer() { this->has_child = false; }
~MyContainer() {
if (!this->has_child) {
// What to do here?
}
}
}
您可以使用 std::optional (C++17 起),这不会导致动态内存分配。例如
class MyContainer {
bool has_child;
std::optional<MyChild> child;
public:
MyContainer(MyChild child) : child(child) { this->has_child = true; }
MyContainer() { this->has_child = false; }
~MyContainer() { /* nothing special need to do */ }
};
顺便说一句:成员 has_child
可以替换为 std::optional::has_value()
。
我不确定我是否会推荐它,但您可以在大小正确的数组中使用 placement new 来做到这一点。
作为一个最小的工作示例:
#include<iostream>
struct MyChild {
~MyChild() { std::cout << "destructor" << std::endl; }
};
class MyContainer {
bool drop;
char arr[sizeof(MyChild)];
MyChild *child;
public:
MyContainer(bool drop)
: drop{drop}, child{::new(&arr) MyChild{}}
{}
~MyContainer() {
if (drop) { child->~MyChild(); }
}
};
void f() {
std::cout << "f" << std::endl;
MyContainer cont{true};
}
void g() {
std::cout << "g" << std::endl;
MyContainer cont{false};
}
int main() {
f();
g();
}
如您所见,MyChild
的析构函数仅在 f
中调用。在 MyContainer
中,无论何时你想访问 MyChild
的实例,你都可以通过 child
数据成员来实现。当然,它不是动态分配的。
我有一个类似 union 的 class,其成员可能是也可能不是垃圾,具体取决于也在同一 class 中设置的布尔标志。
显然,当我的 class 超出范围时,我不希望这些垃圾被销毁。如何防止 class 成员被破坏?
我知道这可以通过指针和动态分配的内存来实现,但我正在寻找更简单的解决方案。
class MyContainer {
bool has_child;
MyChild child;
public:
MyContainer(MyChild child) { this->has_child = true; this->child = child; }
MyContainer() { this->has_child = false; }
~MyContainer() {
if (!this->has_child) {
// What to do here?
}
}
}
您可以使用 std::optional (C++17 起),这不会导致动态内存分配。例如
class MyContainer {
bool has_child;
std::optional<MyChild> child;
public:
MyContainer(MyChild child) : child(child) { this->has_child = true; }
MyContainer() { this->has_child = false; }
~MyContainer() { /* nothing special need to do */ }
};
顺便说一句:成员 has_child
可以替换为 std::optional::has_value()
。
我不确定我是否会推荐它,但您可以在大小正确的数组中使用 placement new 来做到这一点。
作为一个最小的工作示例:
#include<iostream>
struct MyChild {
~MyChild() { std::cout << "destructor" << std::endl; }
};
class MyContainer {
bool drop;
char arr[sizeof(MyChild)];
MyChild *child;
public:
MyContainer(bool drop)
: drop{drop}, child{::new(&arr) MyChild{}}
{}
~MyContainer() {
if (drop) { child->~MyChild(); }
}
};
void f() {
std::cout << "f" << std::endl;
MyContainer cont{true};
}
void g() {
std::cout << "g" << std::endl;
MyContainer cont{false};
}
int main() {
f();
g();
}
如您所见,MyChild
的析构函数仅在 f
中调用。在 MyContainer
中,无论何时你想访问 MyChild
的实例,你都可以通过 child
数据成员来实现。当然,它不是动态分配的。