0

我有一个小的家庭作业问题。
给出以下代码:

int * p;
p = new int;
*p = 5;

问题是:为什么这样做没用

p = 0;
delete p;

但很有用

delete p;
p = 0;

?

在我看来,两者都没有用。如果删除了对象,则无法分配新值。
在这两种情况下我也得到了一个Segmentation fault.

4

5 回答 5

5

为什么它对以下有用:

delete p;
p = 0;

引用 stroustrup 的回答:为什么不将其操作数删除为零?

考虑

delete p;
// ...
delete p;

如果 ... 部分没有触及 p 那么第二个“删除 p;” 是一个严重的错误,C++ 实现不能有效地保护自己免受(没有异常的预防措施)。由于根据定义删除零指针是无害的,因此一个简单的解决方案是“删除 p;”。做一个“p = 0;” 在它完成任何其他需要之后。但是,C++ 不保证这一点。 一个原因是 delete 的操作数不必是左值。考虑:

delete p+1;
delete f(x);

在这里,delete 的实现没有可以分配零的指针。这些例子可能很少见,但它们确实暗示了不可能保证any pointer to a deleted object is 0.'' A simpler way of bypassing thatrule'' 是有两个指向一个对象的指针:

T* p = new T;
T* q = p;
delete p;
delete q;   // ouch!

C++ 明确允许删除的实现将左值操作数清零,我曾希望实现能够做到这一点,但这个想法似乎并没有在实现者中流行。 如果您认为将指针归零很重要,请考虑使用销毁函数:

template<class T> inline void destroy(T*& p) { delete p; p = 0; }

考虑这个通过依赖标准库容器、句柄等来最小化显式使用 new 和 delete 的另一个原因。

请注意,将指针作为引用传递(以允许指针归零)具有防止为右值调用 destroy() 的额外好处:

int* f();
int* p;
// ...
destroy(f());   // error: trying to pass an rvalue by non-const reference
destroy(p+1);   // error: trying to pass an rvalue by non-const reference
于 2013-04-29T02:53:01.340 回答
2

0回想一下,允许删除。因此,当你这样做时

p = 0;
delete p; // Deleting zero is ignored

你扔掉旧的值p(从而造成内存泄漏),然后调用delete 0被忽略。

然而,当你这样做时

delete p;
p = 0;

您首先使用旧值(取消分配int),然后才将其归零。这是有道理的,因为一旦执行旧值,p就会变得既无用又危险delete

于 2013-04-29T02:50:39.760 回答
0

这会将指针设置为 null,然后调用 delete:

p = 0;
delete p;

这就像说

delete 0;

我认为您在想的是它将 p 指向的 int 设置为零,但可以这样做:

*p = 0;
于 2013-04-29T02:50:28.270 回答
0

在第一种情况下,您将 POINTER p 的值分配为“0”,而不是 p 指向的 int 的值。这就是为什么它既无用(实际上会导致内存泄漏),并且当您尝试从内存地址“0”删除时会导致段错误。编辑 - 实际上我刚刚了解到段错误不是由“删除 0”引起的,根据标准,它被忽略了,所以是其他原因造成的。

在第二种情况下,您正在释放 p 指向的内存/对象(这应该没问题),然后将指针分配为具有值“0”,这也应该是好的,所以不知道为什么你在那里出现段错误? 就有用性而言,将 free'd 指针设置为 null 或 '0' 值被认为是一种很好的做法,这样您就可以在取消引用它们之前对其进行测试。

于 2013-04-29T02:52:52.237 回答
0
p = NULL;

p = 0;

在上述情况下,您将值分配给指针而不是它指向的对象。

是一回事。删除函数用于释放动态分配给对象的内存。

  1. 当你说

    delete p;
    p = 0;
    

    这就像说释放分配给指针 p 的内存,然后你说将指针分配给 NULL。哪个是对的。

  2. 在另一种情况下,当你这样做时

    p = 0;
    delete p;
    

    您是说先将指针分配给 NULL 。现在指针 p 没有指向任何有效的动态分配内存。因此,稍后当您说 delete p 时,编译器找不到任何要释放的内存,因此会引发分段错误。

于 2013-04-29T03:00:36.803 回答