我有一个小作业问题 提供以下代码:
int * p;
p = new int;
*p = 5;
问题是:为什么这样做无用
p = 0;
delete p;
但有用
delete p;
p = 0;
?
在我看来,两者都没用。如果删除了某个对象,则不能分配新值
我在这两种情况下都得到Segmentation fault
。
答案 0 :(得分:5)
为什么它对以下内容有用:
delete p;
p = 0;
引自stroustrup的回答:Why doesn't delete zero out its operand?
考虑
delete p; // ... delete p;
如果...部分没有触及p则第二个“删除p;”是一个严重的错误,C ++实现无法有效地保护自己(没有异常的预防措施)。 由于根据定义删除零指针是无害的,因此一个简单的解决方案是“删除p;”做一个“p = 0;”在完成其他任何需要之后。但是,C ++并不保证。 一个原因是删除的操作数不必是左值。考虑:
delete p+1; delete f(x);
这里,delete的实现没有指向零的指针。这些示例可能很少见,但它们确实意味着无法保证
any pointer to a deleted object is 0.'' A simpler way of bypassing that
规则''有两个指向对象的指针:T* p = new T; T* q = p; delete p; delete q; // ouch!
C ++明确允许delete的实现将左值操作数归零,我曾希望实现会这样做,但这个想法似乎并没有受到实现者的欢迎。 如果您认为将指针归零很重要,请考虑使用destroy函数:
template<class T> inline void destroy(T*& p) { delete p; p = 0; }
考虑这个 - 另一个原因是依靠标准库容器,句柄等来最小化对new和delete的显式使用。
请注意,将指针作为引用传递(以允许指针为零)可以防止对rvalue调用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
答案 1 :(得分:2)
回想一下,允许删除0
。因此,当你这样做时
p = 0;
delete p; // Deleting zero is ignored
你丢弃p
的旧值(从而造成内存泄漏),然后调用被忽略的delete 0
。
但是,当你这样做时
delete p;
p = 0;
首先使用旧值(取消分配int
),然后将其归零。这是有道理的,因为p
的旧值在执行delete
后变得无用且危险。
答案 2 :(得分:0)
这将指针设置为null,然后调用delete:
p = 0;
delete p;
就像说
delete 0;
我认为你在想的是它设置了p指向零的int,但是这样就可以这样做:
*p = 0;
答案 3 :(得分:0)
在第一种情况下,您将POINTER p的值指定为“0”,而不是p指向的int的值。这就是为什么它既无用(实际上会导致内存泄漏),并且当你尝试从内存地址'0'删除时会导致seg错误。编辑 - 实际上我刚刚得知段错误不是由'删除0'引起的,根据标准被忽略,所以其他东西导致了。
在第二种情况下,你释放p指向的内存/对象(应该没问题),然后将指针赋值为'0',这也应该是Ok,所以不确定为什么你是那里有错误吗?在有用性方面,过去被认为是将free'd指针设置为null或'0'值的好习惯,因此您可以在取消引用之前对其进行测试。
答案 4 :(得分:0)
p = NULL;
和
p = 0;
在上面的例子中,您要为指针赋值,而不是指向它所指向的对象。
是同一个人。 delete函数用于释放动态分配给对象的内存。
当你说
时delete p;
p = 0;
这就像说释放分配给指针p的内存 那你要说指针指向NULL。哪个是对的。
在您执行此操作的其他情况下
p = 0;
delete p;
您说首先将指针指定为NULL。现在指针p 没有指向任何有效的动态分配内存。好迟啊 当你说删除p时,编译器找不到任何可以释放的内存 因而引发了分段错误。