C++ Is&;arr[size]有效吗?

C++ Is&;arr[size]有效吗?,c++,arrays,language-lawyer,undefined-behavior,C++,Arrays,Language Lawyer,Undefined Behavior,假设我有一个函数,叫做: void mysort(int *arr, std::size_t size) { std::sort(&arr[0], &arr[size]); } int main() { int a[] = { 42, 314 }; mysort(a, 2); } 我的问题是:mysort(更具体地说,&arr[size])的代码是否定义了行为 我知道如果替换为arr+size,它将非常有效;指针算法允许正常指向端点。但是,我的问题是关于&和[]的

假设我有一个函数,叫做:

void mysort(int *arr, std::size_t size)
{
  std::sort(&arr[0], &arr[size]);
}

int main()
{
  int a[] = { 42, 314 };
  mysort(a, 2);
}
我的问题是:
mysort
(更具体地说,
&arr[size]
)的代码是否定义了行为

我知道如果替换为
arr+size
,它将非常有效;指针算法允许正常指向端点。但是,我的问题是关于
&
[]
的使用

根据C++11 5.2.1/1,
arr[size]
相当于
*(arr+size)

引用5.3.1/1,一元
*
规则:

一元
*
运算符执行间接寻址:应用它的表达式应是指向 对象类型,或指向函数类型的指针,结果是引用对象或函数的左值 表达式所指向的。如果表达式的类型为“指向
T
”,则结果的类型为“
T
” [注:指向不完整类型(cv
void
除外)的指针可以被取消引用。由此获得的左值 可以以有限的方式使用(例如,初始化引用);此左值不能转换为 prvalue,见4.1.-结束注释]

最后,5.3.1/3给出了
的规则:

一元
&
运算符的结果是指向其操作数的指针。操作数应为左值。。。如果 表达式为
T
,结果类型为“指向
T
”,是指定对象的地址(1.7)的PR值或指向指定函数的指针

(强调和省略号是我的)

这件事我拿不定主意。我确信在
arr[size]
上强制进行左值到右值的转换是未定义的。但是代码中没有这样的转换<代码>arr+大小
不指向对象;但是,尽管上面的段落讨论了对象,但它们似乎从未明确指出对象实际存在于该位置的必要性(与4.1/1中的左值到右值转换不同)

因此,问题是:
mysort
,它的调用方式,是否有效


(请注意,我在上面引用了C++11,但如果在以后的标准/草案中更明确地处理这一点,我将非常高兴)。

只要大小不大于实际数组的大小(以数组元素为单位),它就非常好且定义良好


因此,如果main()调用mysort(a,100),&arr[size]将是未定义的行为(但很可能未被检测到,但std::sort显然也会出现严重错误)

> P>在正常C++数组的上下文中,是的。通过数组的结束元素形成一个的地址是合法的。然而,读取或写入它所指向的内容是不合法的(毕竟,这里没有实际的元素)。因此,当您执行
&arr[size]
时,
arr[size]
形成您可能认为是对结束元素之后的元素的引用,但尚未尝试实际访问该元素。然后,
&
获取该元素的地址。由于没有任何人试图实际遵循该指针,因此没有发生任何不好的事情

这不是偶然的,这使得数组指针的行为类似于迭代器。因此
&a[0]
本质上是数组上的
.begin()
,而
&a[size]
(其中size是数组中的元素数)本质上是
.end()
。(另请参见
std::array
,此处的内容更加明确)


编辑:嗯,我可能不得不收回这个答案。虽然它可能适用于大多数情况,但如果数组中存储的类型具有重写的
运算符&
,则当您执行
&a[size]
时,
运算符&
方法可能会尝试访问
a[size]处类型实例的成员
在没有实例的情况下

假设
大小
是实际数组大小,则将指向结束元素的指针传递给
std::sort()

因此,据我所知,问题归结为:这个指针是否等同于
arr.end()

毫无疑问,这适用于所有现有编译器,因为数组迭代器确实是普通的旧指针,因此
&arr[size]
显然是
arr.end()
的选择

然而,我怀疑对于普通旧数组迭代器的实际实现是否有特定的要求

因此,为了讨论这个问题,您可以想象一个编译器在实际地址之外使用一个“过去结束”位在内部实现普通的旧数组迭代器,如果它检测到迭代器和通过指针算法获得的地址之间存在任何可调和的不一致,就会反常地将您的胡子涂成粉红色。
这个奇怪的编译器会导致很多现有C++代码崩溃而不违反规范,这可能是值得设计的。

它无效。您在问题中加粗了“result是一个左值,表示表达式指向的对象或函数”。这正是问题所在<代码>数组+大小
是不指向对象的有效指针值。因此,您对
*(数组+大小)
的引用没有指定结果所指的内容,这意味着
&*(数组+大小)
不需要给出与
数组+大小
相同的值


在C语言中,这被认为是一个缺陷并已修复,因此规范现在在
&*ptr
中指出,
&
*
都没有得到评估。C++还没有收到固定的措辞。这是一个非常古老的仍然活跃的DR的主题:。其目的是它是有效的,就像在C中一样,但标准没有这样说。

如果我们承认
arr[i]