临时数组的元素本身不是重值吗?

Aren't elements of a temporary array rvalues themselves?

本文关键字:数组 元素      更新时间:2023-10-16
using intArray = int[];
int (&a) [4] = intArray{1, 2, 3, 4};

这是不允许的,因为将非const左值引用绑定到临时(右值)是非法的。g++ 4.9.1和clang 3.4.2都带着错误返回;当a是符合const条件的

int const (&a) [4] = intArray{1, 2, 3, 4};

然而,当我这样做时

int &x = intArray{1, 2, 3, 4} [1];

两个编译器都可以很好地编译它,没有错误。挖掘标准(草案N3337)对此,§5.2.1 Subscripting

1后缀表达式后跟方括号中的表达式是后缀表达式。其中一个表达式的类型应为"指向T的指针",另一个表达式的类型应为无作用域枚举或整型。结果是类型为"T"的左值。类型"T"应该是完全定义的对象类型。表达式E1[E2]与(根据定义)*((E1)+(E2))

相同。

2 带括号的init-list不能与内置下标操作符一起使用。

  1. 如果我使用1,那么我不明白为什么标准允许构建临时数组,因为在其中下标一个元素会给出一个左值,即我可以从临时数组中获得一个左值,这与临时数组只能绑定到const左值引用或右值引用的原始概念相矛盾。

  2. 如果我去2那么为什么编译器不抛出错误,当我做{1, 2, 3, 4}[1] ?

问题1

关于不将临时值绑定到左值的规则并不能提供绝对的安全性。它可以防止这类错误的一部分,但不是全部。我怀疑,为了防止所有这些错误,需要将"临时"的概念纳入类型系统,就像const一样。然后,如果您知道不会将引用保存的时间超过临时引用的生命周期,则可以"抛弃临时引用"。委员会认为我们现有的规则是值得的,想必他们也认为继续努力是不值得的。

另一个例子,vector<int>(4)[0]也返回一个左值,即使operator[]调用是在临时对象上进行的。标准不会因为这个而禁止临时向量的构造,我也不认为它应该禁止临时数组。好的,所以vector是一个用户定义的类型,而数组是内置的,但除此之外,我认为情况是相似的。

如果您使用数组,特别是临时数组,那么在某种程度上,标准认为您得到了您应得的。它不会仅仅因为可以从临时数组中获得左值就禁止使用临时数组。

但是,我认为你有一个有效的总体观点。下标可能可以在数组右值上更安全地定义,因为编译器有必要的信息。它可以求值为右值,其值为对应数组元素的值。这可能会令人困惑或不方便,因为它与通常的下标表达式不一致,但它会更安全:-)如果你写struct A {int a;},那么A().a是一个右值,所以我不认为将该原则应用于数组是完全不可能的。当然,这将是一个突破性的变化。

问题2

没有在大括号初始化列表上使用下标。您是在使用new-style初始化器语法构造的临时对象上使用它。也就是说,表达式解析的是(intArray{1, 2, 3, 4})[1],而不是intArray({1, 2, 3, 4}[1])