使用临时数组作为左值
Using a temporary array as an lvalue
程序格式错误:
struct X { int i; };
int main() {
(X { }).i = 1;
}
i
是临时X { }
的子对象,不能用作左值,因为X { }
是右值。
但是,它会在GCC 5.2.1和-Wall
中静默编译:
using Y = int[10];
int main() {
(Y { })[0] = 1;
}
如果编译器是正确的,那么这次(Y { })
的第0个元素((Y { })
的子对象)可以作为左值处理。
我的问题是:
- 第二个程序格式错误吗?
- 为什么(不),即使两个程序似乎都将临时对象的子对象视为左值?
我相信第二种情况是错误的,如果我正确地阅读缺陷报告1213,它说:
因为下标操作被定义为通过a的间接操作指针值,下标操作符应用于x值的结果Array是左值,而不是右值。这可能会让一些人感到惊讶。
,解决方案是对c++标准草案第5.2.1节[expr]的以下更改。Sub],(添加了粗体部分,删除了):
后缀表达式后跟方括号中的表达式是A后缀表达式。其中一种表述形式为 " T的数组"或 "指向T的指针",另一个必须是非作用域枚举类型或整型。结果是
为左值,否则为xvalue。和类型的左值"t"类型"T"应该是一个完全定义的对象类型的表达式E1[E2]等于(根据定义)*((E1)+(E2))[注:参见5.3 [expr]。[1]和5.7 [expr。*和+和的详细信息添加[]8.3.4 (dcl。Array]查询阵列的详细信息。-end note],但对于数组操作数,该操作数的结果为左值
Y{}
的结果是5.2.3
[exp .type.conv]:
类似地,一个简单的类型说明符或类型名称说明符后跟一个大括号init-list创建指定类型的临时对象Direct-list-initialized(8.5.4)使用指定的大括号初始化列表,它的值是
所以(Y { })[0]
的结果应该是一个x值,因此是病态的,因为赋值要求在左操作数上有一个可修改的左值:
赋值操作符(=)和复合赋值操作符都从右向左分组。都需要一个
我们可以在c++ 14标准草案的缺陷报告中找到更新的措辞,所以这个更改是在c++ 11之后应用的,但也可能适用于c++ 11,因为这是通过缺陷报告应用的。
为什么section 5.3.1
[expr.unary.]Op]也没有更新对我来说是不清楚的,说结果是左值似乎有点不一致,这不是在所有情况下。
更新
提交了clang bug报告
c++标准草案(N4527)§5.2.1条款1规定:
表达式E1[E2]与(根据定义)*((E1)+(E2))相同
§5.3.1第1条规定:
一元*操作符是间接执行的:应用该操作符的表达式必须是指向对象类型的指针,或指向函数类型的指针,且操作结果是指向该表达式所指向的对象或函数的左值。
- Mongodb c++驱动程序:如何查询元素的数组
- 将数组的地址分配给变量并删除
- 从C++本机插件更新Vector3数组
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 数组索引的值没有增加
- 将对象数组的引用传递给函数
- 为char数组调整zlib-zpipe
- 2D数组来自文本输入,中间有空格
- std::向量与传递值的动态数组
- 在c++中用vector填充一个简单的动态数组
- 使用strcpy将char数组的元素复制到另一个数组
- 使用指针从C++中的数组中获取最大值
- C++使用整数的压缩数组初始化对象
- 告诉一个 const char 数组,除了编译时 C 样式的字符串外,它不以 '