C++ 在delete()之后不会断言两个指针都指向NULL
给出这段代码:C++ 在delete()之后不会断言两个指针都指向NULL,c++,struct,assert,C++,Struct,Assert,给出这段代码: #include <iostream> #include <assert.h> using namespace std; struct Foo { // something }; int main() { Foo *p1 = new Foo; Foo * p2 = p1; assert(NULL != p1); delete p1; p1 = NULL; assert(NULL != p2
#include <iostream>
#include <assert.h>
using namespace std;
struct Foo
{
// something
};
int main()
{
Foo *p1 = new Foo;
Foo * p2 = p1;
assert(NULL != p1);
delete p1;
p1 = NULL;
assert(NULL != p2);
delete p2;
cout << "everything is cool!" << endl;
return 0;
}
#包括
#包括
使用名称空间std;
结构Foo
{
//某物
};
int main()
{
Foo*p1=新的Foo;
Foo*p2=p1;
断言(NULL!=p1);
删除p1;
p1=零;
断言(NULL!=p2);
删除p2;
库特
当我删除p1时,第二个断言(assert(NULL!=p2);)不是
失败了,为什么
删除p1
或分配给它对p2
本身没有影响。删除p1
后,p2
仍然指向该地址,即指向一个不存在的对象。它成为所谓的悬挂指针。当然,访问或删除它(您正在执行的操作)“未定义的行为”。 <代码>代码>删除p;< /COD>不影响<代码> P<代码>。它破坏了代码> P>代码>指向的对象并释放其内存。<代码> P<代码>仍然具有它以前的值。 < P> C++中初学者误称最大的和最令人困惑的一个术语是“删除指针”。。这无疑源于以下事实:delete
表达式将指针作为其参数:
T * p = new T; // #1
delete p; // #2
然而,真正发生的是第1行创建了一个新的、动态的、未命名的对象。请再想想:没有变量的值是第1行中创建的对象。该对象确实是遥不可及的,因为它确实不在任何范围内。我们所拥有的只是一个指向它的指针
为了结束动态变量的生命周期,我们必须使用delete
表达式。但是,因为我们已经知道,我们只能真正拥有一个指向对象的指针,而不是对象本身*,因此表达式可以方便地接受指向我们正在删除的对象的指针
因此,实际上我们应该说,在第2行中,“我们正在删除对象*p
,方法是给它一个指向delete
表达式的指针”(即&*p==p
)
指针本身完全不受delete
调用的影响
*)是的,我们也可以有一个引用变量,比如T&r=*newt;
,但那太疯狂了
尤其是看星星
int i;
int *p1 = &i;
assert(p1 != NULL);
int *p2 = p1;
assert(p2 != NULL);
*p1 = 10;
assert(i == 10);
assert(*p2 == 10);
p1 = NULL; // does not affect the object p1 was pointing at
assert(i == 10);
assert(*p2 == 10);
assert(p2 != NULL); // (which we already know, if the previous assert didn't crash)
你怀疑一切都不酷是对的。程序在同一个对象上调用delete操作符两次(“双重自由”错误),这可能会损坏堆。如果程序继续运行,您将在某个点上看到未定义的行为。如果有未定义的行为,则会破坏编写计算机程序的意义。如果您希望立即明确地看到类似这样的错误,请在valgrind的memcheck或下运行它
因为p2仍然被设置为p1拥有的任何地址。更改后,它不会获得p1的值。“非法”应该是“未定义的行为”@tenfour我只是厌倦了“未定义的行为”,我想尝试一些不同的方法。