我有一个带有成员的A类,它是另一个B类的对象指针的向量
class A
{
std::vector<B*> m_member_A
通过使用m_member_A
运算符创建B的对象来填充 new
B* b1 = new B;
m_member_A.push_back(b1);
在A的析构函数中,以下是正确的以释放所有内容吗?
A::~A()
{
for(int i = 0; i < m_member_A.size(); ++i)
{
delete m_member_A[i];
}
m_member_A.clear();
}
答案 0 :(得分:5)
这是正确的,只要你还有Rule of Three的正确的复制构造函数和复制赋值运算符。请注意,clear()
是多余的,因为向量的析构函数将释放其内存。
你为什么乱搞指针和new
?为什么不遵循Zero规则,如果需要指向多态的指针,请使用vector<B>
或vector<unique_ptr<B>>
?那么你根本不需要担心析构函数,复制构造函数或复制赋值运算符;并且你将获得移动语义作为奖励。
答案 1 :(得分:4)
是的,这是正确的......但这还不够。
每当复制A
时,您还需要对容器进行深层复制。
如果你可以在矢量中使用智能指针,那就更好了。请在您的头脑和代码中清楚知道谁拥有什么。
答案 2 :(得分:3)
概
如果在A的构造函数中构造(分配)B的元素,而某些B抛出异常,则会发生内存泄漏(除非它在A的构造函数中被捕获,其中B的删除已完成)
通常的三条规则。
可能有一些插图(请将MAKE_FAILURE调整为0或1):
#include <iostream>
#include <stdexcept>
#include <vector>
#define MAKE_FAILURE 0
static unsigned count;
const unsigned ExceptionThreshold = 3;
struct B {
B() { if(ExceptionThreshold <= count++) throw std::runtime_error("Sorry"); }
~B() { std::cout << "Destruct\n"; }
};
struct A
{
std::vector<B*> v;
A()
{
for(unsigned i = 0; i < ExceptionThreshold + MAKE_FAILURE; ++i)
v.push_back(new B);
}
~A()
{
for(unsigned i = 0; i < v.size(); ++i) {
delete v[i];
}
}
};
int main()
{
A a;
return 0;
}
此外,你进入浅层和深层复制的地形(如@所述) Orb中的轻盈比赛)
答案 3 :(得分:2)
这是在m_member_A向量中释放动态分配对象的内存的正确方法。你实际上不需要打电话:
m_member_A.clear();
std :: vector将自行释放内存。
如果您可以使用C ++ 11,那么我建议您更改为shared_ptr:
std::vector<std::shared_ptr<B>> m_member_A
现在你不需要自己释放记忆。