具有正确地址和类型的指针是否仍然始终是有效指针

具有正确地址和类型的指针是否仍然始终是有效指针

本文介绍了自 C++17 以来,具有正确地址和类型的指针是否仍然始终是有效指针?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C++17标准之前,中包含了下面这句话[basic.compound]/3:

如果类型 T 的对象位于地址 A,则称其值为地址 A 的类型为 cv T* 的指针指向该对象,无论该值是如何获得的.

但从 C++17 开始,这句话已经删除.

例如我相信这句话定义了这个示例代码,并且因为 C++17 这是未定义的行为:

 alignas(int) unsigned char buffer[2*sizeof(int)];auto p1=new(buffer) int{};自动 p2=new(p1+1) int{};*(p1+1)=10;

在C++17之前,p1+1保存着*p2的地址并且类型正确,所以*(p1+1) 是一个指向 *p2 的指针.在 C++17 p1+1 是一个 指针越过结尾,所以它不是指向对象的指针,我相信它是不可解引用的.

这是对标准权利的这种修改的解释还是有其他规则可以弥补引用句子的删除?

解决方案

是的,这个解释是正确的.超过末尾的指针不能简单地转换为恰好指向该地址的另一个指针值.

新的 [basic.compound]/3 说:>

指针类型的每个值都是以下之一:
(3.1)指向对象或函数的指针(该指针被称为指向对象或函数),或
(3.2)超过对象末尾的指针([expr.add]),或

那些是相互排斥的.p1+1 是指向末尾的指针,而不是指向对象的指针.p1+1 指向 p1 处的 size-1 数组的假设 x[1],而不是 p2>.这两个对象不是指针可相互转换的.

我们也有非规范性说明:

[ 注意:超出对象末尾的指针 ([expr.add]) 不被视为指向可能位于该地址的对象类型的无关对象.[...]

阐明了意图.


作为 T.C.在众多评论中指出(尤其是这个),这确实是尝试实现 std::vector 所带来的问题的一个特例 - 即 [v.data(), v.data() + v.size()) 需要是一个有效范围,但 vector 不创建数组对象,所以唯一的定义的指针算术将从向量中的任何给定对象到其假设的单一大小数组的末尾.如需更多资源,请参阅 CWG 2182此标准讨论,以及关于该主题的论文的两次修订:P0593R0P0593R1(特别是第 1.3 节).

Before the C++17 standard, the following sentence was included in [basic.compound]/3:

But since C++17, this sentence has been removed.

For example I believe that this sentence made this example code defined, and that since C++17 this is undefined behavior:

 alignas(int) unsigned char buffer[2*sizeof(int)];
 auto p1=new(buffer) int{};
 auto p2=new(p1+1) int{};
 *(p1+1)=10;

Before C++17, p1+1 holds the address to *p2 and has the right type, so *(p1+1) is a pointer to *p2. In C++17 p1+1 is a pointer past-the-end, so it is not a pointer to object and I believe it is not dereferencable.

Is this interpretation of this modification of the standard right or are there other rules that compensate the deletion of the cited sentence?

解决方案

Yes, this interpretation is correct. A pointer past the end isn't simply convertible to another pointer value that happens to point to that address.

The new [basic.compound]/3 says:

Those are mutually exclusive. p1+1 is a pointer past the end, not a pointer to an object. p1+1 points to a hypothetical x[1] of a size-1 array at p1, not to p2. Those two objects are not pointer-interconvertible.

We also have the non-normative note:

which clarifies the intent.


As T.C. points out in numerous comments (notably this one), this is really a special case of the problem that comes with trying to implement std::vector - which is that [v.data(), v.data() + v.size()) needs to be a valid range and yet vector doesn't create an array object, so the only defined pointer arithmetic would be going from any given object in the vector to past-the-end of its hypothetical one-size array. Fore more resources, see CWG 2182, this std discussion, and two revisions of a paper on the subject: P0593R0 and P0593R1 (section 1.3 specifically).

这篇关于自 C++17 以来,具有正确地址和类型的指针是否仍然始终是有效指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 10:19