确实在对象指针上调用delete递归删除其动态分配的成员

时间:2020-06-23 20:59:17

标签: c++ destructor delete-operator

如果我有一个包含动态分配的类B实例的类A,是否在指向A实例的指针(当然是从new接收到)的指针上调用delete也会有效地释放B实例所占用的内存?还是A的析构函数必须显式调用B实例上的delete才能使之发生?

1 个答案:

答案 0 :(得分:1)

这取决于您如何在B类型中存储指向A的指针。

class B;

class A {
private:
    SomePointer m_b;
};

什么是SomePointer

  • 如果为B*,则为否,自动删除此B分配是不是。您将需要实现析构函数A::~A()并将其删除。不要忘记删除/实现复制/移动构造/分配功能,否则复制/移动操作将导致两个A拥有相同的B并导致(除其他外)东西)的双重自由问题。
  • 如果是std::unique_ptr<B>,那么恭喜您,您做出了正确的选择,而您无需做任何事情。 A的隐式定义的析构函数将销毁std::unique_ptr<B>,这将为您删除分配的B。此外,将正确隐式定义move构造函数/赋值函数(假设A的其余数据成员是可移动的),并且A的复制操作将被隐式删除,因为它们将不正确。格式(std::unique_ptr<B>不可复制)。

这是这两种方法的一个例子。它们都允许对A执行相同的操作。首先,使用原始指针:

class A {
public:
    A();

    // Need custom move logic.
    A(A &&);
    A & operator=(A &&);

    // Prevent copying.
    A(A const &) = delete;
    A & operator=(A const &) = delete;

    ~A();

private:
    B * m_b;
};

A::A() : m_b{nullptr} { }

A::~A() { delete m_b; }

A::A(A && other) : A{} { *this = std::move(other); }

A & A::operator=(A && other) {
    using std::swap;
    swap(m_b, other.m_b);
    return *this;
}

现在使用std::unique_ptr<B>

class A {
private:
    std::unique_ptr<B> m_b;
}

您想维持哪一个?哪个更容易正确?

相关问题