问题描述
我有代码:
std::list<Node *> lst;
//....
Node * node = /* get from somewhere pointer on my node */;
lst.remove(node);
std::list::remove
方法是否调用每个移除元素的析构函数(和空闲内存)?如果是这样,我该如何避免?
Does the std::list::remove
method call the destructor (and free memory) of each removed element? If so, how I can avoid it?
推荐答案
是的,从容器中移除 Foo*
会破坏 Foo*
,但不会释放Foo
.销毁一个原始指针总是没有操作.它不可能是任何其他方式!让我给你几个原因.
Yes, removing a Foo*
from a container destroys the Foo*
, but it will not release the Foo
. Destroying a raw pointer is always a no-op. It cannot be any other way! Let me give you several reasons why.
删除指针只有在指针实际是动态分配的情况下才有意义,但是运行时怎么可能知道指针变量被销毁时是否是这种情况?指针还可以指向静态和自动变量,删除其中之一会产生未定义的行为.
Deleting a pointer only makes sense if the pointee was actually allocated dynamically, but how could the runtime possibly know whether that is the case when the pointer variable is destroyed? Pointers can also point to static and automatic variables, and deleting one of those yields undefined behavior.
{
Foo x;
Foo* p = &x;
Foo* q = new Foo;
// Has *q been allocated dynamically?
// (The answer is YES, but the runtime doesn't know that.)
// Has *p been allocated dynamically?
// (The answer is NO, but the runtime doesn't know that.)
}
悬空指针
无法确定过去是否已经释放了指针对象.两次删除相同的指针会产生未定义的行为.(第一次删除后它变成了一个悬空指针.)
Dangling pointers
There is no way to figure out whether the pointee has already been released in the past. Deleting the same pointer twice yields undefined behavior. (It becomes a dangling pointer after the first delete.)
{
Foo* p = new Foo;
Foo* q = p;
// Has *q already been released?
// (The answer is NO, but the runtime doesn't know that.)
// (...suppose that pointees WOULD be automatically released...)
// Has *p already been released?
// (The answer WOULD now be YES, but the runtime doesn't know that.)
}
未初始化的指针
也根本无法检测指针变量是否已被初始化.猜猜当您尝试删除这样的指针时会发生什么?再一次,答案是未定义的行为.
{
Foo* p;
// Has p been properly initialized?
// (The answer is NO, but the runtime doesn't know that.)
}
动态数组
类型系统不区分指向单个对象的指针 (Foo*
) 和指向对象数组的第一个元素的指针(还有 Foo*
).当指针变量被销毁时,运行时无法确定是通过 delete
还是通过 delete[]
释放指针对象.通过错误的形式发布会调用未定义的行为.
Dynamic arrays
The type system does not distinguish between a pointer to a single object (Foo*
) and a pointer to the first element of an array of objects (also Foo*
). When a pointer variable is destroyed, the runtime cannot possibly figure out whether to release the pointee via delete
or via delete[]
. Releasing via the wrong form invokes undefined behavior.
{
Foo* p = new Foo;
Foo* q = new Foo[100];
// What should I do, delete q or delete[] q?
// (The answer is delete[] q, but the runtime doesn't know that.)
// What should I do, delete p or delete[] p?
// (The answer is delete p, but the runtime doesn't know that.)
}
总结
由于运行时不能对指针对象做任何有意义的事情,销毁指针变量总是是一个空操作.什么都不做肯定比由于不知情的猜测而导致未定义的行为更好:-)
Summary
Since the runtime cannot do anything sensible with the pointee, destroying a pointer variable is always a no-op. Doing nothing is definitely better than causing undefined behavior due to an uninformed guess :-)
代替原始指针,考虑使用智能指针作为容器的值类型,因为它们负责在不再需要指针时释放指针.根据您的需要,使用 std::shared_ptr
或 std::unique_ptr
.如果您的编译器还不支持 C++0x,请使用 boost::shared_ptr
.
Instead of raw pointers, consider using smart pointers as the value type of your container, because they take responsibility for releasing the pointee when it is no longer needed. Depending on your need, use std::shared_ptr<Foo>
or std::unique_ptr<Foo>
. If your compiler does not support C++0x yet, use boost::shared_ptr<Foo>
.
从来没有,我再说一遍,从来没有使用std::auto_ptr
作为容器的值类型.
Never, I repeat, NEVER EVER use std::auto_ptr<Foo>
as the value type of a container.
这篇关于std::list::remove 方法是否调用每个已删除元素的析构函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!