关于c ++ 11:删除后的c ++中的指针

Pointers in c++ after delete

在阅读了很多关于这方面的文章之后,我想澄清下一点:

1
2
3
4
5
6
7
A* a = new A();
A* b = a;

delete a;

A* c = a; //illegal - I know it (in c++ 11)
A* d = b; //I suppose it's legal, is it true?

所以问题是如何使用已删除指针副本的值。

我已经读到,在C++ 11中,读取EDOCX1的值(0)会导致未定义的行为,但是读取EDOCX1的值1呢?

Trying to read the value of the pointer (note: this is different to
dereferencing it) causes implementation-defined behaviour since C++14,
which may include generating a runtime fault. (In C++11 it was
undefined behaviour)
What happens to the pointer itself after delete?


两者:

1
2
A* c = a;
A* d = b;

在C++ 11中未定义,并且在C++ 14中定义了实现。这是因为EDCOX1 1和EDCOX1×2 }都是"无效指针值"(因为它们指向释放的存储空间),并且"使用无效指针值"是未定义的或实现定义的,这取决于C++版本。("使用"包括"复制的价值")。

C++ 11中的相关部分(EDOCX1×10)读取(强调添加):

If the argument given to a deallocation function in the standard library is a pointer that is not the null pointer value (4.10), the deallocation function shall deallocate the storage referenced by the pointer, rendering invalid all pointers referring to any part of the deallocated storage. The effect of using an invalid pointer value (including passing it to a deallocation function) is undefined.

非规范性说明:

On some implementations, it causes a system-generated runtime

在C++ 14中,同一部分读取:

If the argument given to a deallocation function in the standard library is a pointer that is not the null pointer value (4.10), the deallocation function shall deallocate the storage referenced by the pointer, rendering invalid all pointers referring to any part of the deallocated storage. Indirection through an invalid pointer value and passing an invalid pointer value to a deallocation function have unde?ned behavior. Any other use of an invalid pointer value has implementation-de?ned behavior.

非规范性说明:

Some implementations might de?ne that copying an invalid pointer value causes a system-generated runtime fault


不应在delete后面使用指针。下面这个使用acessing a的例子是基于实现定义的行为。(感谢M.M.和Mankarse的指点)

我觉得在这里重要的不是变量a(或bcd,而是值(=释放块的内存地址),在某些实现中,当在某些"指针上下文"中使用时,它可以触发运行时错误。

这个值可能是一个右值/表达式,不一定是存储在变量中的值-所以我不相信EDOCX1的值(我使用松散的"指针上下文"来区别于在非指针相关表达式中使用相同的值,即相同的位集-这不会导致运行时错误)。

------------我的原始帖子如下。-

你的实验就快到了。只需添加一些cout,如下所示:

1
2
3
4
5
6
7
8
class A {};
A* a = new A();
A* b = a;
std::cout << a << std::endl;   // <--- added here
delete a;
std::cout << a << std::endl;   // <--- added here. Note 'a' can still be used!
A* c = a;
A* d = b;

调用delete a对变量a没有任何作用。这只是图书馆的电话。管理动态内存分配的库保留已分配内存块的列表,并使用变量a传递的值将以前分配的一个块标记为释放。

虽然Mankarse引用C++文档是真实的,但是:"呈现无效的所有指针指向释放的存储的任何部分"-注意变量EDCOX1(1)的值仍然未被触动(您没有通过引用传递,而是通过值传递)。.

因此,总结并尝试回答您的问题:

delete之后,变量a仍存在于范围内。变量a仍然包含相同的值,这是为class A的对象分配(现在已经释放)的内存块的起始地址。技术上可以使用a的该值-例如,可以像在上面的示例中一样打印它-但是很难找到比打印/记录过去更合理的使用方法…您不应该做的是尝试取消引用这个值(它也保存在变量bcd中),因为这个值不再是有效的内存指针。

您永远不应该依赖于被释放的存储对象(尽管它很可能会在那里停留一些时间,因为C++不需要清除在使用后释放的存储)-您没有保证,也没有安全的方式来检查这一点。


这2行没有任何区别(意思是C++的合法性):

1
2
A* c = a; //illegal - I know it (in c++ 11)
A* d = b; //I suppose it's legal, is it true?

你的错误(这是很常见的)是,如果你在a上称delete,它会使它与b有任何不同。你应该记住,当你在指针上调用delete时,你通过值传递参数,所以内存,其中a指向delete之后,就不再可用了,但是这个调用不会使a与你例子中的b有任何不同。