【发布时间】:2018-06-12 05:46:12
【问题描述】:
在C++17标准之前,[basic.compound]/3中包含了下面这句话:
如果一个类型为 T 的对象位于地址 A 处,则称其值为地址 A 的类型为 cv T* 的指针指向该对象,而不管该值是如何获得的。
但是从C++17开始,这句话一直是removed。
例如,我相信这句话定义了这个示例代码,并且从 C++17 开始,这是未定义的行为:
alignas(int) unsigned char buffer[2*sizeof(int)];
auto p1=new(buffer) int{};
auto p2=new(p1+1) int{};
*(p1+1)=10;
在 C++17 之前,p1+1 持有指向*p2 的地址并且具有正确的类型,因此*(p1+1) 是指向*p2 的指针。在 C++17 中,p1+1 是 pointer past-the-end,所以它不是 指向对象的指针,我相信它是不可取消引用的。
这是对标准权修改的这种解释,还是有其他规则可以补偿引用句子的删除?
【问题讨论】:
-
注意:在 [basic.stc.dynamic.safety] 和 [util.dynamic.safety] 中有关于指针来源的新/更新规则
-
@M.M 这只对具有严格指针安全性的实现很重要,它是一个空集(在实验错误范围内)。
-
引用的陈述在实践中从未真正成立过。给定
int a, b = 0;,即使您检查了&a + 1 == &b,您也不能执行*(&a + 1) = 1;。如果仅仅通过猜测地址就可以得到一个有效的指向对象的指针,那么即使将局部变量存储在寄存器中也是有问题的。 -
@T.C. 1) 哪个编译器在您获取其地址后将 var 放入 reg 中? 2)如何在不测量地址的情况下正确猜测地址?
-
@curiousguy 正是这就是为什么简单地将通过其他方式(例如,猜测)获得的数字转换为对象恰好所在的地址是有问题的:它为该对象起别名,但编译器不知道它。相反,如果您按照您所说的那样获取对象的地址:编译器会收到警告并相应地同步。
标签: c++ pointers c++14 language-lawyer c++17