此代码在 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 行肯定引用相同的 x
作为C 行,所以看起来 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]
是一个 xvalue。
Foo()
是纯右值,因此访问非静态成员会产生缺值。因为 Foo.x
是一个 xvalue,Foo.x[0]
也是一个 xvalue,不能赋值给它。
关于c++ - 临时对象的字段是右值吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44447031/