临时数组的元素不是rvalues自己吗?

leg*_*s2k 10 c++ arrays temporary rvalue c++11

using intArray = int[];
int (&a) [4] = intArray{1, 2, 3, 4};
Run Code Online (Sandbox Code Playgroud)

这是不允许的,因为将非const左值引用绑定到临时(rvalue)是非法的.g ++ 4.9.1和clang 3.4.2都有错误; 当它编译罚款aconst合格的

int const (&a) [4] = intArray{1, 2, 3, 4};
Run Code Online (Sandbox Code Playgroud)

但是,当我这样做

int &x = intArray{1, 2, 3, 4} [1];
Run Code Online (Sandbox Code Playgroud)

两个编译器都编译好没有错误.挖这个标准(N3337草案),§5.2.1 Subscripting说:

1后缀表达式后跟方括号中的表达式是后缀表达式.其中一个表达式应具有"指向T的指针"类型,另一个表达式应具有未映射的枚举或整数类型.结果是类型"T"的左值.类型" T"应该是完全定义的对象类型.表达式E1 [E2]与*((E1)+(E2))相同(根据定义)

2 braced-init-list不能与内置的下标运算符一起使用.

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

  2. 如果我选择2,那么为什么编译器在我做的时候不会抛出错误{1, 2, 3, 4}[1]

Ste*_*sop 4

问题1

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

再例如,vector<int>(4)[0]即使operator[]调用是临时的,也返回左值。该标准不会因此而禁止构造临时向量,而且我也不认为它应该禁止临时数组。好吧,vector用户定义的类型也是如此,而数组是内置的,但除此之外,我认为情况是相似的。

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

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

问题2

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