我已经看过它多次断言现在C++标准不允许使用以下代码:
int array[5];
int *array_begin = &array[0];
int *array_end = &array[5];
Run Code Online (Sandbox Code Playgroud)
&array[5]在这种情况下是合法的C++代码吗?
如果可能的话,我想要一个参考标准的答案.
知道它是否符合C标准也很有趣.如果它不是标准的C++,为什么决定做出从不同的治疗呢array + 5还是&array[4] + 1?
我在这里使用N3936作为参考(如果任何C++ 14文本不同,请更正此问题).
在3.10 Lvalues和rvalues下,我们有:
每个表达式都属于此分类法中的基本分类之一:lvalue,xvalue或prvalue.
但是左值的定义是:
的左值 [...]表示一个功能或一个对象.
在4.1 Lvalue-to-rvalue转换中,文本显示:
[...]在所有其他情况下,转换的结果根据以下规则确定:[...]否则,glvalue指示的对象中包含的值是prvalue结果.
我的问题是:在左值不指定对象的代码中会发生什么?有两个典型的例子:
例1:
int *p = nullptr;
*p;
int &q = *p;
int a = *p;
Run Code Online (Sandbox Code Playgroud)
例2:
int arr[4];
int *p = arr + 4;
*p;
int &q = *p;
std::sort(arr, &q);
Run Code Online (Sandbox Code Playgroud)
哪些行(如果有的话)格式不正确和/或导致未定义的行为?
参考实施例1:是*p左值?根据我的第一句话,它必须是.但是,我的第二个引文排除了它,因为*p没有指定一个对象.(它肯定不是xvalue或prvalue).
但是如果你将我的第二个引用解释*p为实际上是一个左值,那么它就不会被左值到右值转换规则所覆盖.您可以采用全部规则"标准未定义的任何内容是未定义的行为",但是只要没有执行左值到右值的转换,就必须允许空引用存在.
历史:此问题在DR 232中提出.在C++ 11中,DR232的分辨率确实出现了.引用N3337 Lvalue -to-rvalue转换:
如果glvalue引用的对象不是类型T的对象,并且不是从T派生的类型的对象,或者如果对象未初始化,则需要此转换的程序具有未定义的行为.
它似乎仍然允许空引用存在 - 它只清除了在一个上执行左值到右值转换的问题.也讨论了这个SO线程
DR232的分辨率不再出现在N3797或N3936中.