对于原始数组和std::vector,明显没有对下标进行过一次结束的说明.这个问题已经得到了决定性的解决吗?



以前已经以各种形式提出过这个问题,但是由于语言规范在这方面似乎是相当动态的(或者至少在对这个问题进行一些SO讨论时动态的),因此根据最近的发展(如果有的话)重新审视这个问题可能是有意义的。

那么,问题又来了,&和下标的组合是否是一种有效的方法来获得指向数组

的虚过尾元素的指针
int a[42] = {};
&a[42];

在c++ 98中被认为没有定义。但是现代c++呢?我们已经看到了DR#232,但由于某种原因,它仍处于"起草"状态,绝对不在标准文本中(从c++ 14开始)。这件事还悬而未决,还是已经用别的办法解决了?

有趣的是DR#315似乎公开允许通过空指针p(!)调用非静态成员函数,其基础是"*pp为空时不会出错,除非将左值转换为右值"。DR#315的分辨率似乎是暂时基于DR#232的未来分辨率,但后者未能实现。从这个角度来看,DR 315真的是NAD吗?

此外,自c++ 11以来,标准库规范将可解引用的迭代器定义为*it表达式有效的迭代器,在std::vector的情况下,这可能会在很大程度上将问题委托给原始数组的上述问题,显然为可解引用的std::vector::end()迭代器打开了大门。这可能使以下代码有效
std::vector<int> v(42);
&v[42];

真的有效吗?一些关于SO的旧答案明确地指出,解引用标准end()迭代器总是未定义的。但在c++ 11之后的版本中,它似乎没有那么清晰。标准指出,标准库实现"从不假设"end-iterator是可解引用的,这意味着它们不再是无条件不可解引用的。

注:我已经在c++ 14中看到过这种左值不指定对象的讨论,但它似乎特别关注引用初始化的有效性,我不想在这里带来

据我所知,您在&v[42](或&a[42])表达式中对其进行了解引用,并且未定义。

基于N4140的

:

[expr.unary.op]/1

一元*操作符间接执行表达式必须是指向对象的指针类型,或指向函数类型的指针,且结果为左值指向表达式所指向的对象或函数。

我不认为数组最后一个元素之后的非元素是对象

我猜:

除了为类(13.5.5)声明外,下标操作符[]的解释方式如下E1[E2]等于*((E1)+(E2))

a[42]等于*(a + 42)

[§5.7加性运算符]

当一个整型表达式在指针上加减时,结果具有整型指针操作数的。…

…如果指针操作数和结果都指向同一个数组对象的元素,或一个过去数组对象的最后一个元素,计算不会产生溢出;否则,行为为定义。

所以a + 42似乎返回一个有效的T*指针,它将解引用到T (per [expr.unary.op])

如果表达式的类型是"指向T的指针",则结果的类型是" t "

还有以下注释:

[§3.9.2复合类型]

注意:例如:数组末尾后面的地址(5.7)将被认为指向数组元素类型的一个不相关的对象,该对象可能位于该地址上。

它似乎是有效的。我仍然认为分配给它将是未定义的行为(由于注释,它是一个不相关的对象),但获取地址似乎是定义的。

话虽这么说,&a[41] + 1是定义的(感谢5.7),并完全避免了这一点,也许只是这样做。

最新更新