【发布时间】:2020-10-14 00:56:58
【问题描述】:
如果我有一个包含动态分配的 B 类实例的 A 类,对指向 A 实例的指针调用 delete(当然是从 new 接收的)是否也有效地释放 B 实例占用的内存?还是 A 的析构函数必须在 B 的实例上显式调用 delete 才能发生这种情况?
【问题讨论】:
标签: c++ destructor delete-operator
如果我有一个包含动态分配的 B 类实例的 A 类,对指向 A 实例的指针调用 delete(当然是从 new 接收的)是否也有效地释放 B 实例占用的内存?还是 A 的析构函数必须在 B 的实例上显式调用 delete 才能发生这种情况?
【问题讨论】:
标签: c++ destructor delete-operator
这取决于您如何在 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;
}
你更愿意维护哪一个?哪一个更容易做对?
【讨论】: