我有关于删除操作符的问题。如果有3个实例,每个实例都持有下一个/上一个实例,如何删除它?
class A : public Parent
{
privte:
A* next;
A* previous;
public:
void setNext(A*);
void setPrevious(A*);
};
..
int main()
{
A* obj1 = new A();
A* obj2 = new A();
A* obj3 = new A();
obj1->setNext(obj2);
obj2->setNext(obj3);
obj3->setNext(nullptr);
obj1->setPrevious(nullptr);
obj2->setPrevious(obj1);
obj3->setPrevious(obj2);
return 0;
}
如果我删除obj1 .. obj2和obj3自动删除。为什么?这是内存泄漏吗?他们真的被删除了吗?我不明白这种行为。每个新的都不应该删除吗?
答案 0 :(得分:1)
您必须考虑资源所有权问题。你做出了一些政策决定。然后编写确认该政策的代码。
执行后:
obj1->setNext(obj2);
谁拥有obj2
? obj2
拥有obj1
?它是由调用函数还是更高级别的对象拥有的?
如果您的政策说明obj1
拥有obj2
,那么您在删除obj2
时必须删除obj1
。
如果您的政策说调用函数或更高级别的对象拥有obj2
,则删除obj2
时不得删除obj1
。
你问:
如果我删除obj1 .. obj2和obj3自动删除。为什么呢?
因为您没有编写删除它们的代码。
这是内存泄漏吗?
是
它们真的被删除了吗?
没有
我不明白这种行为。每个新的都不应该删除吗?
是。应该。但是,您必须确保从delete
返回的每个对象都调用new
。
如果您的政策是obj1
在上述电话会议后拥有obj2
,则您必须实施A
的析构函数才能删除next
和previous
。但是,在执行此操作之前,必须确保正确处理链接。否则,您将遇到已被删除的指针,如果您没有正确处理链接,则会遇到内存泄漏。
~A()
{
// Hopefully next->previous points to this.
// You have to unlink next from this. Otherwise, 'delete next' will end up calling
// delete on 'this`.
// Similarly with previous
if ( next != nullptr )
{
next->previous = nullptr;
delete next;
}
if ( previous!= nullptr )
{
previous->next= nullptr;
delete previous;
}
}
您仍然需要致电
delete obj1;
在main
中以确保删除所有对象。
如果您的策略是调用函数或更高级别的对象在语句后拥有objt2
obj1->setNext(obj2);
你必须在调用函数的所有对象上调用delete。
int main()
{
A* obj1 = new A();
A* obj2 = new A();
A* obj3 = new A();
obj1->setNext(obj2);
obj2->setNext(obj3);
obj3->setNext(nullptr);
obj1->setPrevious(nullptr);
obj2->setPrevious(obj1);
obj3->setPrevious(obj2);
delete obj3;
delete obj2;
delete obj1;
return 0;
}
为了使它更清洁,你应该处理一个类似于std::list
的更高级别的容器。您可以在列表中添加和删除项目。删除列表时,必须确保删除所有包含的元素。