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)
编译器有不同的结果:
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. - 尾注]
顺便说一句,我建议在网络编译器上使用rextester,因为rextester允许你共享你的程序并且还有实时共享.
更新
Ben Voigt指出了这个错误报告,因此看起来Visual Studio实际上产生了一个左值.所以这不仅仅是扩展的一种情况,它允许临时对象绑定到非const左值引用.
更新2
Mgetz提交了一个错误报告,响应是这是通过使用/ Zc:rvalueCast标志来修复的,标志的描述如下:
当指定/ Zc:rvalueCast选项时,编译器会根据C++ 11标准正确识别rvalue引用类型作为强制转换操作的结果.如果未指定该选项,则编译器行为与Visual Studio 2012中的相同.默认情况下,/ Zc:rvalueCast处于关闭状态.为了保持一致性并消除使用强制转换的错误,我们建议您使用/ Zc:rvalueCast.
目前还不清楚在将来的版本中是否会默认启用此标志.
是的,转换为对象类型的结果是右值,如 C++11 5.4/1 所指定:
T
如果T 是左值引用类型或函数类型的右值引用,则结果是左值;如果 T 是对象类型的右值引用,则结果是 xvalue;否则结果是纯右值。
在标准 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 有一个扩展允许右值绑定到非常量引用;该扩展仍然使右值引用比右值引用更好的匹配。