为什么不删除将指针设置为NULL?
我总是想知道为什么在删除之后指针自动设置为NULL不是标准的一部分。 如果这得到照顾,那么由于无效指针而导致的许多崩溃不会发生。 但是说了一下,我可以想一下为什么标准会限制这个原因的几个原因:
性能:
额外的指令可能会降低
delete
性能。难道是因为
const
指针?然后标准可能已经做了这个特殊的情况我猜。
有没有人知道不允许这个的确切原因?
Stroustrup自己回答。 摘录:
C ++明确允许一个实现删除来清除一个左值操作数,我曾希望实现会这样做,但是这个想法似乎并没有成为实施者的stream行。
但他提出的主要问题是删除的论点不必是左值。
首先,设置为空将需要一个内存存储variables。 确实,你通常在一个variables中有一个指针,但是有时你可能想要在一个刚刚计算的地址删除一个对象。 这是不可能的“删除”删除。
然后是性能。 您可能已经编写了代码,使得指针在删除完成后立即超出范围。 用空值填充只是浪费时间。 而C ++是一种语言,“不需要它,那么你不必为此付出”的意识形态。
如果您需要安全,您可以为您提供各种各样的智能指针,或者您可以自己编写 – 更好,更智能。
你可以有多个指向这个内存的指针。 如果您为删除指定的指针设置为空,则会产生错误的安全感,但所有其他指针都不会。 指针不过是一个地址,一个数字。 这也可能是一个取消引用操作的int。 我的观点是你也必须扫描每一个指针,find那些引用你刚才删除的内存的那些指针,然后把它们清空。 扫描该地址的所有指针并将其清零是计算密集型的,因为该语言不是为此devise的。 (尽pipe其他一些语言的结构也是以不同的方式来完成类似的目标的。
一个指针可以保存在多个variables中,将其中的一个设置为NULL仍然会在其他variables中留下无效的指针。 所以你真的没有多less收获,你更可能造成一种虚假的安全感。
除此之外,你可以创build你自己的function:
template<typename T> void deleten(T *&ptr) { delete ptr; ptr = NULL; }
因为实际上没有必要,而且因为它需要删除指针指针而不是指针。
delete
主要用于析构函数,在这种情况下,将成员设置为NULL是毫无意义的。 几行后,在closures}
,成员不再存在。 在赋值运算符中,无论如何,删除之后通常都是一个赋值。
而且,它会使下面的代码变得非法:
T* const foo = new T; delete foo;
如果你有一个指针数组,而你的第二个动作是删除空的数组,那么当内存即将被释放时,没有意义设置每个值为null。 如果你想它为null ..写入null 🙂
C ++允许你定义你自己的操作符new和delete,以便例如他们使用你自己的池分配器。 如果你这样做,那么可以使用新的和删除不是严格地址的东西,而是在你的池数组中声明索引。 在这种情况下,NULL(0)的值可能具有合法含义(指池中的第一项)。
所以删除自动设置为NULL的参数并不总是具有 – 将值设置为无效值的含义。 无效值可能不总是NULL。
这是另一个原因。 假设delete将其参数设置为NULL:
int *foo = new int; int *bar = foo; delete foo;
应该吧设置为NULL? 你能概括这个吗?
C ++的哲学是“只有使用它才付钱”。 我想这可能会回答你的问题。
有时你可以有自己的堆,这将恢复已删除的内存..或有时指针不属于任何variables。 或者存储在less量variables中的指针 – 可能只是其中的一个。
正如你所看到的,它有许多问题和可能的问题。
将指针自动设置为NULL不会解决大多数指针使用不当的问题。 它会避免的唯一的崩溃是如果你试图删除它两次。 如果你在这样一个指针上调用成员函数呢? 它仍然会崩溃(假设它访问成员variables)。 C ++不会限制你在NULL指针上调用任何函数,从性能的angular度来看也不应该这样做。
我看到人们对这个问题给出了奇怪的答案。
ptr = NULL; 这样一个简单的陈述怎么会导致性能延迟?
另一个答案是说我们可以有多个指针指向同一个内存位置。 我们当然可以。 在这种情况下,对一个指针的删除操作只会使该指针为NULL(如果delete正在使指针为NULL),另一个指针将为非NULL并指向空闲的内存位置。
解决scheme应该是该用户应该删除指向同一位置的所有指针。 内部应该检查内存是否已经释放,而不是释放。 只能使指针为NULL。
Stroustrup本可以devise删除以这种方式工作。 他认为程序员会照顾这个。 所以他忽略了。