C++ 删除已删除的对象:行为?

C++ 删除已删除的对象:行为?,c++,pointers,memory-management,delete-operator,C++,Pointers,Memory Management,Delete Operator,我想知道如果我试图对已经删除或可能尚未分配的指针执行delete,会发生什么?我读过两件事:首先,delete操作符将进行一些检查,我们不需要检查指针是否为空;然后,我读到它会导致未知的行为 我这样问是因为我使用了一些包含Qt对象属性的个人对象;我认为Qt会在我们关闭窗口时删除所有相关的小部件,但我仍然不太确定:如果软件在窗口关闭之前崩溃,我们必须手动删除所有对象 那么,最好的解决方案是什么?像这样的 if( my_object ) delete my_object; 它能避免危险行为

我想知道如果我试图对已经删除或可能尚未分配的指针执行
delete
,会发生什么?我读过两件事:首先,
delete
操作符将进行一些检查,我们不需要检查指针是否为空;然后,我读到它会导致未知的行为

我这样问是因为我使用了一些包含Qt对象属性的个人对象;我认为Qt会在我们关闭窗口时删除所有相关的小部件,但我仍然不太确定:如果软件在窗口关闭之前崩溃,我们必须手动删除所有对象

那么,最好的解决方案是什么?像这样的

if( my_object )
    delete my_object;
它能避免危险行为吗

if( my_object )
    delete my_object;
这是多余的<在
NULL
指针上,code>delete不执行任何操作。这是由标准保证的

delete
对已删除的指针执行删除操作会导致未定义的行为。这就是为什么在删除指针后,应始终记住将指针分配到
NULL

delete p;
p = NULL;

编辑:根据评论,我觉得我应该指定这一点。如果有多个指向同一对象的指针,则将其赋值为NULL不会使删除安全。无论如何,最好使用智能指针。

delete
对已存在的
delete
d非空指针是未定义的行为-您的程序可能会崩溃。您可以在空指针上安全地使用
delete
——它将产生一个no-op

因此,真正的问题不是对空指针执行
delete
。真正的问题在于:

 ptr = new Something();
 otherPtr = ptr;
 delete ptr;
 delete otherPtr;
如果有多个指针指向同一个对象,则会发生这种情况,这是非常危险的。可能的解决办法是:

  • 使用智能指针(代码中无
    删除
    )或
  • 只有一个指定指针用于控制每个对象的生存期,并在正确的时间删除

如果在已经
delete
d指针上调用
delete
,则会导致未定义的行为。
不过,在
NULL
指针上调用
delete
没有任何效果

标准c++03§3.7.4.2-3

如果释放函数通过抛出异常终止,则该行为未定义。提供给解除分配函数的第一个参数的值可以是空指针值;如果是,并且如果解除分配函数是标准库中提供的函数,则调用无效。否则,将返回提供的值 标准库中的to operator
delete(void*)
应为先前调用operator
new(std::size\u t)
或标准库中的
operator new(std::size\u t,const std::nothrow\u-t&)
返回的值之一,以及提供给operator
delete[](void*))标准库中的
应为先前调用
运算符new[](std::size\u t)
标准库中的运算符新[](std::size\u t,const std::nothrow\u t&)


使用智能指针是避免此类问题的最佳武器。

请注意,删除指针不会将其设置为空

int* i = new int;
*i = 42;
delete i;
delete i; // oops! i is still pointing to the same memory, but it has been deleted already
删除空指针没有任何作用,删除已删除的对象将导致未定义的行为。

正确的方法是:

if( my_object )
{
    delete my_object;
    my_object = NULL;
}

因为,按以前的方式调用两次将在
deleted
指针上调用
delete

只需结合以上答案:

  • if(my_对象)检查指针的值,而不是对象的存在。如果已删除,指针仍可能指向该位置
  • 删除已删除的对象是未定义的行为,可能会使程序崩溃
  • 已定义删除NULL,但不执行任何操作。这与第1点一起解释了路钦的答案

总而言之:您必须明确对象的所有者以及指向该对象的不同指针的位置。删除对象时,请确保将指向该位置的所有指针设置为0/NULL。使用诸如boost::shared_pointer或QPointer之类的管理对象来帮助您完成此任务。

“可能崩溃”是一种轻描淡写的说法,UB可能会使猛禽跳入您的窗口并使宇宙内爆。@refp:我知道,但新手通常不相信。您的答案有误导性,您是说删除会将指针设置为0吗?没有<代码>删除ptr;删除ptr也同样危险。@乔·麦格拉斯:不,我不是这么说的。
删除ptr的问题;删除ptr是人们以“愚蠢,没人会那样做”为由拒绝它。@sharptooth我不确定“可能的崩溃”。至少我使用过一个实现,第二次删除是不可操作的。除非内存已经被重新分配,在这种情况下,新所有者会有点意外:-)。我们都知道,在未定义行为的情况下,最常见的“行为”是程序与您的所有测试完美配合,然后在重要客户面前的演示中崩溃。只希望它会正确崩溃,而不是失去您的业务instead@sehe:LOL.我想未来的标准中会有这样的文字-正确的碰撞行为,应该正确的崩溃等。学习现代C++,永远不要使用<代码>删除< /代码>。我不同意这个建议。首先,它可能会使问题变得更糟,因为您会养成这样的习惯,即如果您有一个非空值的指针,则可以安全地删除它,而事实并非如此。(例如,请参见sharptooth的回答。)这只会消除错误。让它崩溃,这样你就可以摆脱双重删除/提醒你使用智能指针。这里有一个关于删除对象后指针的值的解释。