施放的结果是左值?

use*_*077 15 c++ standards casting lvalue visual-c++

int a = 0;
Run Code Online (Sandbox Code Playgroud)

那么是标准C++中(int)a右值

不同的编译器显示此代码的不同结果:

#include <iostream>
using namespace std;

void f(int& x)
{
    cout << "l value" << endl;
}

void f(int&& x)
{
    cout << "r value" << endl;
}

int main()
{
    int a = 0;
    f((int)a);
}
Run Code Online (Sandbox Code Playgroud)

编译器有不同的结果:

1)http://cpp.sh/2r6

2)http://webcompiler.cloudapp.net/

Sha*_*our 10

应该是一个右值,webcompiler正在运行Visual Studio,Visual Studio有一个扩展,允许临时对象绑定到非const左值引用. 在这种情况下产生左值的错误/扩展,正如伊戈尔所指出的那样,可以使用来禁用/Za(请参见实时).

我们可以看到它应该是一个rvalue(特别是一个prvalue)来自草案C++标准部分5.4 显式类型转换(强制表示法)1段,它说(强调我的):

表达式(T)cast-expression的结果是T类型.如果T是左值引用类型或函数类型的右值引用,则结果是左值;如果T是对象类型的右值引用,则结果是xvalue; 否则结果是一个prvalue.[注意:如果T是cv限定的非类型类型,则在确定结果prvalue的类型时将忽略cv限定符; 见3.10. - 尾注]

无论GCC结果右值这是预期的结果.

顺便说一句,我建议在网络编译器上使用rextester,因为rextester允许你共享你的程序并且还有实时共享.

更新

Ben Voigt指出了这个错误报告,因此看起来Visual Studio实际上产生了一个左值.所以这不仅仅是扩展的一种情况,它允许临时对象绑定到非const左值引用.

正如dyp所指出的,gcc曾经也有一个强制转换为左值扩展.

更新2

Mgetz提交了一个错误报告,响应是这是通过使用/ Zc:rvalueCast标志来修复的,标志的描述如下:

当指定/ Zc:rvalueCast选项时,编译器会根据C++ 11标准正确识别rvalue引用类型作为强制转换操作的结果.如果未指定该选项,则编译器行为与Visual Studio 2012中的相同.默认情况下,/ Zc:rvalueCast处于关闭状态.为了保持一致性并消除使用强制转换的错误,我们建议您使用/ Zc:rvalueCast.

目前还不清楚在将来的版本中是否会默认启用此标志.


Mik*_*our 5

是的,转换为对象类型的结果是右,如 C++11 5.4/1 所指定:

T如果T 是左值引用类型或函数类型的右值引用,则结果是左值;如果 T 是对象类型的右值引用,则结果是 xvalue;否则结果是纯右值

  • 关键是没有规则规定从“T”到“T”的强制转换是例外。 (6认同)

M.M*_*M.M 5

在标准 C++ 中int(a)并且(int)a是右值(其他答案提供标准参考)。

您的代码示例正在利用 MSVC 中的错误/扩展,但不是乍一看的样子。正如我们从这段适用于 MSVC 的代码中看到的:

#include <iostream>

int main()
{
    int x = 0;
    (int)x = 1;
    std::cout << x << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

MSVC 将其(int)x视为左值。

尽管 MSVC 有一个扩展允许右值绑定到非常量引用;该扩展仍然使右值引用比右值引用更好的匹配。