c++ - `f().a[0]` 是一个 xvalue 吗?

标签 c++

struct S{
    int a[3] = {1,2,3};
};

S&& f(){return S();}

&f().a;       //[Error] taking address of xvalue (rvalue reference)
&f().a[0];    //ok in GCC 5.1.0 and Clang 3.6.0

S s;
&static_cast<S&&>(s).a;     //[Error] taking address of xvalue (rvalue reference)
&static_cast<S&&>(s).a[0];  //ok in GCC 5.1.0 and Clang 3.6.0

5.7 An expression is an xvalue if it is:

(7.1) — the result of calling a function, whether implicitly or explicitly, whose return type is an rvalue reference to object type,

(7.2) — a cast to an rvalue reference to object type,

(7.3) — a class member access expression designating a non-static data member of non-reference type in which the object expression is an xvalue, or

(7.4) — a .* pointer-to-member expression in which the first operand is an xvalue and the second operand is a pointer to data member.

5.2.1 Subscripting 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 of type “T”. The type “T” shall be a completely-defined object type. The expression E1[E2] is identical (by definition) to *((E1)+(E2))<<*t [ Note: see 5.3 and 5.7 for details of * and + and 8.3.4 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.

所以,是 f().a[0]一个xvalue?

我认为f().a[0]应该是一个 xvalue。


[编辑1]

忽略 &f().a;&f().a[0];因为 12.2[class.temporary]p5.2

The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not extended; the temporary is destroyed at the end of the full-expression in the return statement

static_cast<S&&>(s).a是一个 xvalue(7.2 和 7.3)。

"除了在数组操作数的情况下,如果该操作数是左值,则结果是左值,否则是 xvalue。"

所以我认为static_cast<S&&>(s).a[0]应该是一个 xvalue,但是

&static_cast<S&&>(s).a[0]; //ok in GCC 5.1.0 and Clang 3.6.0

任务:

我错了吗?如果我错了,请给我一个例子,下标数组会产生一个 xvalue。

最佳答案

据我所知,这确实是正确的,这看起来是一个“错误”,尽管公平地说这最近随着CWG defect 1213 发生了变化|其中说:

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.

这改变了第 5.2.1 节 [expr.sub] 如下:

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.

所以确实是 f().a[0]; 的结果和 static_cast<S&&>(s).a[0]应该是 xvalues。

此缺陷直到 2012 年 12 月才提出解决方案,clangs defect report support将该缺陷报告的支持列为未知,因此很可能实现者尚未修复此缺陷。

更新

提交了 clang bug report: Subscript operator applied to an temporary array results in an lvalue .

关于c++ - `f().a[0]` 是一个 xvalue 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46747728/

相关文章:

c++ - 为什么这个函数调用不明确?

c++ - 运算符重载中的成员二元运算符和非成员二元运算符

c++ - 从函数返回二维 double 组

c++ - 查找对象是否属于C++中的类

c++ - 对 vtable 的 undefined reference ...

c++ - MSVC 中 std::vector::push_back 的实现

c++ - boost::interprocess : managed shared memory errors

c++ - Const unsigned char* 到 char*

c++ - Const 正确性 - 如何在 C++ 中访问 vector vector 的元素?

c++ - 移动指针的右值引用