使用临时数组作为左值 [英] Using a temporary array as an lvalue

查看:283
本文介绍了使用临时数组作为左值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

该程序格式不正确:

struct X { int i; };

int main() {
    (X { }).i = 1;
}

临时X { }的子对象

i不能用作左值,因为X { }是右值.

i, a sub-object of the temporary X { }, cannot be used as an lvalue because X { } is an rvalue.

但是,它会与GCC 5.2.1和-Wall一起静默编译:

However, this silently compiles with GCC 5.2.1 and -Wall:

using Y = int[10];

int main() {
    (Y { })[0] = 1;
}

如果编译器正确,则这次,(Y { })的第零个元素(是(Y { })的子对象)可以视为左值.

If the compiler is correct, then this time, the zeroth element of (Y { }), which is a subobject of (Y { }), can be treated as an lvalue.

我的问题是:

  1. 第二个程序格式错误吗?
  2. 为什么(不是),即使这两个程序似乎都将临时的子对象视为左值?

推荐答案

如果我正在阅读

I believe the second case is ill-formed, if I am reading defect report 1213 correctly, it says:

因为下标操作被定义为通过 指针值,应用于xvalue的下标运算符的结果 array是一个左值,而不是一个xvalue.这对于某些人来说可能是令人惊讶的.

Because the subscripting operation is defined as indirection through a pointer value, the result of a subscript operator applied to an xvalue array is an lvalue, not an xvalue. This could be surprising to some.

,解决方案是对C ++标准草案第5.2.1节[expr.sub]的以下更改,(添加了加固的部分,并删除了删除线):

and the resolution was the following changes to the draft C++ standard section 5.2.1 [expr.sub], (bolded sections were added and strikethroughs were removed):

后缀表达式后跟方括号的表达式是 后缀表达式.表达式之一应具有以下类型: "T的数组"或"T的指针",另一个应具有无范围的枚举或整数类型.结果是一个左值 T."类型"T"应为完全定义的对象类型.62 表达式E1 [E2](根据定义)与*((E1)+(E2))相同[注: 有关*和+的详细信息,请参见5.3 [expr.unary]和5.7 [expr.add]. 8.3.4 [dcl.array]了解数组的详细信息. —end note] ,除了在数组操作数的情况下,如果该操作数为结果,则结果为左值 是左值,否则是x值.

A postfix expression followed by an expression in square brackets is a postfix expression. One of the expressions shall have the type "array of T" or "pointer to T" and the other shall have unscoped enumeration or integral type. The result is an lvalue of type "T." The type "T" shall be a completely-defined object type.62 The expression E1[E2] is identical (by definition) to *((E1)+(E2)) [Note: see 5.3 [expr.unary] and 5.7 [expr.add] for details of * and + and 8.3.4 [dcl.array] for details of arrays. —end note], except that in the case of an array operand, the result is an lvalue if that operand is an lvalue and an xvalue otherwise.

Y{}的结果是5.2.3 [expr.type.conv] 部分中的prvalue:

The result of Y{} is a prvalue from section 5.2.3 [expr.type.conv]:

类似地,简单类型说明符或类型名称说明符后跟一个 braced-init-list创建指定类型的临时对象 使用指定的括号初始化列表直接初始化列表(8.5.4), 它的值是 将该临时对象作为prvalue.

Similarly, a simple-type-specifier or typename-specifier followed by a braced-init-list creates a temporary object of the specified type direct-list-initialized (8.5.4) with the specified braced-init-list, and its value is that temporary object as a prvalue.

(Y { })[0]的结果应为xvalue,因此格式不正确,因为赋值需要在左操作数上具有可修改的lvalue:

So the result of (Y { })[0] should be an xvalue and therefore ill-formed since assignment requires a modifiable lvalue on the left operand:

赋值运算符(=)和复合赋值运算符都从右到左分组.都需要一个 可修改的左值作为其左操作数[...]

The assignment operator (=) and the compound assignment operators all group right-to-left. All require a modifiable lvalue as their left operand [...]

我们可以在草稿C中从缺陷报告中找到更新的措辞. ++ 14标准,因此此更改是在C ++ 11之后应用的,但由于是通过缺陷报告应用的,因此可能适用于C ++ 11.

We can find the updated wording from the defect report in the draft C++14 standard, so this change was applied after C++11 but may apply to C++11 since this was a applied via a defect report.

为什么还不更新5.3.1 [expr.unary.op] 部分,我不清楚,说结果是 lvalue 似乎有些矛盾并非在所有情况下都如此.

Why section 5.3.1 [expr.unary.op] was not also updated is unclear to me, it seems somewhat inconsistent to say the result is an lvalue which it is not in all cases.

更新

提交了 clang错误报告.

这篇关于使用临时数组作为左值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆