C++ 临时对象的字段是右值吗?

C++ 临时对象的字段是右值吗?,c++,C++,此代码在Clang 3.8、GCC 6.3和VS2013下编译成功,但在Clang 4.0下编译失败: struct Foo { int x[2]; Foo() { x[0] = 3; // line A: works fine - we can assign to x[0] *&x[0] = 4; // line B: works fine - we can take the address of x[0] } }; int main() { Foo(

此代码在Clang 3.8、GCC 6.3和VS2013下编译成功,但在Clang 4.0下编译失败:

struct Foo {
  int x[2];
  Foo() {
    x[0] = 3; // line A: works fine - we can assign to x[0]
    *&x[0] = 4; // line B: works fine - we can take the address of x[0]
  }
};

int main() {
  Foo().x[0] = 5; // line C: error: expression is not assignable
  *(Foo().x + 0) = 6; // line D: works fine
}
哪个编译器是正确的?
Foo().x[0]
是右值还是左值

第A行和第B行在所有编译器上都工作,
x[0]
肯定是一个左值,而第A行和第B行肯定引用了与第C行相同的
x
,因此看起来像
Foo()。x[0]
应该是一个左值。但是当以这种方式访问时,
Foo()
的右值可能会传播到它的所有字段

也考虑行D,它适用于所有编译器。我认为

bar[n]
基本上只是
*(bar+n)
(对于数组)的语法糖,所以D行正常工作而C行失败似乎很奇怪。

Foo().x[0]
在C++11中是一个左值。在C++11中,内置下标运算符的结果始终是左值,因为它涉及取消对指针的引用

在C++14中,内置下标运算符的行为发生了更改:

  • 如果
    a
    是左值,那么
    a[i]
    是左值
  • 否则,
    a[i]
    是一个x值

Foo()
是一个prvalue,因此访问非静态成员会产生一个xvalue。由于
Foo.x
是一个xvalue,
Foo.x[0]
也是一个xvalue,无法分配给它。

您不应该试图修改匿名临时值。此外,如果这样的代码真的运行了,它又有什么意义呢?这只是一个玩具示例。我真正的代码类似于
glUniformMatrix4fv(&Matrix::MakeOrthographic(1,2,3,4).values[0])如果这有意义的话。在我更新Android NDK之前,这段代码一直运行良好,它使用了新版本的Clang,现在给出了“不能获取'float'类型的右值的地址”。所以我把它归结为我所能想到的问题的最简单表达式。@JohnZwinck:例如,临时的析构函数做了一些有趣的事情。来吧
int main(){File(“filename”).data=“abc”}
猜猜
文件的析构函数做什么。你的例子不是最好的。@ CONIO:你的例子不是野外看到的“真正的C++代码的典型”。“调用一种方法,比如<代码>())/代码>是允许的。@好奇你不是在调用内置的<代码> [C]>运算符,而是重载<代码> >代码>操作符<代码> STD::数组< /C> >,这不是REF限定的,因此它总是返回左值。@这是个好问题。向量和字符串也没有ref限定的下标运算符。这可能是一种疏忽,也可能是为了避免违反规则,即
c[i]
*(c.begin()+i)
相同。值得问一个新问题。@quitious@quitious只需比较C++11和C++14中的[expr.sub]standards@Curious我跟踪堆栈溢出。如果你在这里花了足够的时间,忽略QT和作业分配的所有问题,你就会意识到C++的大部分微妙之处。