【问题标题】:does calling delete on an object pointer recursively delete its dynamically allocated members对对象指针调用 delete 是否会递归删除其动态分配的成员
【发布时间】:2020-10-14 00:56:58
【问题描述】:

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

【问题讨论】:

    标签: c++ destructor delete-operator


    【解决方案1】:

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

    class B;
    
    class A {
    private:
        SomePointer m_b;
    };
    

    SomePointer 是什么?

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

    以下是这两种方法的示例。它们都允许对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;
    }
    

    你更愿意维护哪一个?哪一个更容易做对?

    【讨论】:

    • 谢谢!快速跟进 隐式析构函数调用成员对象的析构函数吗?
    • @HashBr0wn 是的。显式声明的析构函数也会这样做;您不能阻止析构函数调用任何子对象的析构函数。显式定义的析构函数用于执行除销毁子对象之外可能需要执行的任何额外操作。
    猜你喜欢
    • 2013-11-17
    • 2012-11-06
    • 1970-01-01
    • 2019-03-28
    • 1970-01-01
    • 2021-10-16
    • 2021-08-05
    • 2013-02-11
    • 2014-05-07
    相关资源
    最近更新 更多