C++ 对对象指针调用delete是否递归删除其动态分配的成员

C++ 对对象指针调用delete是否递归删除其动态分配的成员,c++,destructor,delete-operator,C++,Destructor,Delete Operator,如果我有一个包含动态分配的类B实例的类a,那么对从new接收的指向a实例的指针调用delete当然也会有效地释放B实例占用的内存吗?或者A的析构函数必须显式调用B实例上的delete才能实现这一点吗?这取决于在A类型中如何存储指向B的指针 什么是指针 如果是B*则否,此B分配的删除不是自动的。您需要实现析构函数A::~A并在那里删除它。不要忘记删除/实现复制/移动构造/分配功能,否则复制/移动操作将导致两个拥有相同的B,从而导致双重自由问题。 如果是std::unique\u ptr,那么恭喜你

如果我有一个包含动态分配的类B实例的类a,那么对从new接收的指向a实例的指针调用delete当然也会有效地释放B实例占用的内存吗?或者A的析构函数必须显式调用B实例上的delete才能实现这一点吗?

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

什么是指针

如果是B*则否,此B分配的删除不是自动的。您需要实现析构函数A::~A并在那里删除它。不要忘记删除/实现复制/移动构造/分配功能,否则复制/移动操作将导致两个拥有相同的B,从而导致双重自由问题。 如果是std::unique\u ptr,那么恭喜你,你做出了正确的选择,你不需要做任何事情。A的隐式定义的析构函数将销毁std::unique_ptr,它将删除为您分配的B。此外,移动构造函数/赋值函数将被隐式正确定义,假设A的其余数据成员是可移动的,并且A的复制操作将被隐式删除,因为它们将是格式错误的std::unique_ptr不可复制。 下面是两种方法的一个示例。它们都允许对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\u ptr:


你想保留哪一个?哪一个比较容易正确?

谢谢!快速跟进隐式析构函数是否调用成员对象的析构函数?@HashBr0wn Yes。显式声明的析构函数也会这样做;不能阻止析构函数调用任何子对象的析构函数。显式定义的析构函数用于执行除销毁子对象之外可能需要执行的任何额外操作。
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;
}
class A {
private:
    std::unique_ptr<B> m_b;
}