如何阻止在堆栈分配的对象上调用析构函数?

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 数据成员来实现。当然,它不是动态分配的。