强制转换的结果是右值吗?
让
int a = 0;
那么(int)a
是标准C++中的rvalue吗?
不同的编译器对此代码显示不同的结果:
#include 使用命名空间标准;void f(int& x){cout<<l值"<<结束;}void f(int&& x){cout<<r值"<<结束;}int main(){int a = 0;f((int)a);}
不同结果的编译器:
1) http://cpp.sh/2r6
2) http://webcompiler.cloudapp.net/
解决方案The 应该是一个 rvalue 但是 webcompiler 正在运行 Visual Studio 并且 Visual Studio 有一个 允许将临时对象绑定到非常量左值引用的扩展. 一个错误/扩展,导致它在这种情况下生成左值 就像 Igor上面指出这可以使用 /Za
禁用(现场观看).
我们可以看到它应该是来自 C++ 标准草案部分 5.4
显式类型的 rvalue(特别是 prvalue)转换(转换符号) 段落 1 表示(强调我的):
表达式 (T) cast-expression 的结果是 T 类型.如果 T 是左值引用类型或右值,则结果是左值如果 T 是右值引用,则引用函数类型和 xvalue对象类型;否则结果是纯右值.[ 注意:如果 T 是具有 cv 限定的非类类型,忽略 cv 限定符在确定结果纯右值的类型时;见 3.10.-结尾注意]
gcc 和 clang 结果在 rvalue 这是预期的结果.
顺便说一句,我建议使用 rextester 而不是 webcompiler,因为 rextester 允许您分享您的节目,也有现场分享.
更新
Ben Voigt 指出了这个错误报告,因此似乎 VisualStudio 实际上产生一个左值.因此,这不仅仅是 允许将临时对象绑定到非常量左值引用的扩展的情况.>
正如 dyp 指出的那样 gcc 曾经有一个转换为左值扩展
更新 2
Mgetz 提交了错误报告,得到的答复是已修复通过使用 /Zc:rvalueCast 标志,标志的描述如下:
<块引用>当指定了/Zc:rvalueCast 选项时,编译器正确将右值引用类型标识为强制转换操作的结果符合C++11标准.When the option is not指定,编译器行为与 Visual Studio 2012 中的相同.默认情况下,/Zc:rvalueCast 是关闭的.为了一致性和消除使用强制转换的错误,我们建议您使用/Zc:rvalueCast.
尚不清楚在未来版本中是否会默认启用此标志.
Let
int a = 0;
Then is (int)a
an rvalue in standard C++?
Different compilers show different results for this code:
#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);
}
compilers with different results:
1) http://cpp.sh/2r6
2) http://webcompiler.cloudapp.net/
解决方案The should be an rvalue but webcompiler is running Visual Studio and Visual Studio has an extension which allows temporary objects to be bound to non-const lvalue references. a bug/extension that casues it to generate an lvalue in this case As Igor points out above this can be disabled using /Za
(see it live).
We can see that it should be an rvalue(specifically a prvalue) from the draft C++ standard section 5.4
Explicit type conversion (cast notation) paragraph 1 which says (emphasis mine):
The result of the expression (T) cast-expression is of type T. The result is an lvalue if T is an lvalue reference type or an rvalue reference to function type and an xvalue if T is an rvalue reference to object type; otherwise the result is a prvalue.[ Note: if T is a non-class type that is cv-qualified, the cv-qualifiers are ignored when determining the type of the resulting prvalue; see 3.10. ―end note ]
Both gcc and clang result in rvalue which is the expected result.
As an aside, I would recommend using rextester over webcompiler since rextester allows you to share your program and also has live sharing.
Update
Ben Voigt point out this bug report and so it seems that Visual Studio actually produces an lvalue. So this is not simply a case of the extension which allows temporary objects to be bound to non-const lvalue references.
As dyp points out gcc used to have a cast to lvalue extension as well.
Update 2
Mgetz filed a bug report, the response was that this is fixed by using the /Zc:rvalueCast flag, the description of the flag is as follows:
When the /Zc:rvalueCast option is specified, the compiler correctly identifies an rvalue reference type as the result of a cast operation in accordance with the C++11 standard. When the option is not specified, the compiler behavior is the same as in Visual Studio 2012. By default, /Zc:rvalueCast is off. For conformance and to eliminate errors in the use of casts, we recommend that you use /Zc:rvalueCast.
It is unclear whether this flag will be enabled by default in future versions.
相关文章