假设我们有一个类,它将指针成员保存到另一个对象。如果我在析构函数中删除该指针,我会收到错误(我理解为什么)。
我的问题是:是否有可能在没有内存泄漏的情况下克服这个问题?
以下是我正在做的演示。
class A {
public:
~A() { cout<< "~A()" <<endl; }
};
class B {
A *pA;
public:
B(A* pA) {
this->pA = pA;
}
~B() {
delete pA;
cout<<"~B()"<<endl;
}
};
int main() {
A a;
{
B b2(new A()); //deletes A, deletes B, no memory leaks
}
{
B b(&a); //deletes A, error.
}
return 0;
}
答案 0 :(得分:2)
首先,这不是内存泄漏,而是未定义的行为,这是一个更严重的问题。试图从错误的区域释放记忆
一个人应该仅在相应的delete/delete[]/free()
上使用new/new[]/malloc()
。
没有完全证明和架构独立的方式,只需遵循良好的编程习惯。
总是不完美,但一种方法是重载new
和delete
并保持std::map
类似的数据结构。每当调用new
时,添加指向它的指针。在delete
后,您可以检查指针是否存在,分配是new
类型还是new[]
等。
这肯定会影响您的性能,因此您需要将其保持在调试模式下。
答案 1 :(得分:2)
您有两个对象认为他们拥有动态分配的对象并尝试删除它。解决方案是决定谁应该拥有该对象,并在适当的智能指针的帮助下实现正确的复制/赋值行为:
A
和B
是否处理动态分配的对象?没有办法从原始指针中知道这一点,因此必须修改设计以涵盖一种情况或另一种情况。假设动态对象分配,那么A
或B
中实施三个规则,并且只有两个中的一个删除。您可以使用范围指针来简化内存管理(boost_scoped_ptr
或std::unique_ptr
)。std::unique_ptr
。禁止复制和分配,允许移动复制和移动分配std::shared_ptr
答案 2 :(得分:1)
你必须告诉B
,它何时拥有指针,什么时候不拥有。
添加另一个标志,告知何时
class B {
bool owner;
A *pA;
public:
B(A* pA, bool bOwner) : owner(bOwner) {
this->pA = pA;
}
~B() {
if (owner)
delete pA;
cout<<"~B()"<<endl;
}
};
int main() {
A a;
{
B b2(new A(), true); //deletes A, destroys B, no memory leaks
}
{
B b(&a, false); //destroys B, ok.
}
return 0;
}