如何在传递右值引用函数参数时从基元类型变量复制

How to copy from primitive type variables when passing through rvalue reference function arguments

本文关键字:参数 复制 类型变量 函数 引用      更新时间:2023-10-16

我可以通过复制构造函数从非基元类型变量进行复制,并通过右值引用函数参数传递它。

但是如何使用基元类型变量来实现这一点呢?

例如:

#include <cassert>
#include <iostream>
struct MyClass
{
   int m = 0;
};
MyClass& f(MyClass& x)
{
   x.m++;
   return x;
}
inline MyClass f(MyClass&& x)
{
   return f(x);
}
int& f(int& x)
{
   x++;
   return x;
}
inline int f(int&& x)
{
   return f(x);
}
int main()
{
   MyClass x1;
   auto y1 = f(MyClass(x1)); // Calls f(MyClass&&)
   // Result: x1.m = 0, y1.m = 1
   int x2 = 0;
   auto y2 = f(int(x2)); // Calls f(int&)
   // Result: x2 = 1, y2 = 1
   std::cout << x1.m << x2; // Result in VS2013: '01' But '00' in gcc and clang!
   assert(x1.m == x2); // FAILED in VS2013!!!
   return 0;
}

Visual Studio 2013中的结果为"01",断言失败。

http://rextester.com/CAPY87169

您的代码是正确的,这似乎是VS2013中的一个错误。

更简单的MCVE:

#include <iostream>
void f(int& x)  { std::cout << "f(lv)n"; }
void f(int&& x) { std::cout << "f(rv)n"; }
int main()
{
   int x2 = 0;
   f( int(x2) );
   f( (int)x2 );
}

输出应为:

f(rv)
f(rv)

MSVC在线测试仪

请注意,进一步的测试表明,错误实际上是(int)x2被MSVC视为左值;MSVC的扩展允许右值绑定到左值引用并不是一个错误(因为右值引用无论如何都是更好的匹配)。

您可以使用/Za开关来解决此问题。


表达式int(x2)由C++14[expr.type.conv]/2覆盖(C++11具有相同的编号):

简单类型说明符(7.1.6.2)类型名说明符(14.6)后接带括号的表达式列表构造给定表达式列表的指定类型的值。如果表达式列表是单个表达式,则类型转换表达式与相应的强制转换表达式(5.4)等效(在定义上,如果在含义上定义)

对应的强制转换表达式为:

表达式(T)强制转换表达式的结果为T类型。如果T是左值引用类型或对函数类型的右值引用,则结果为左值;如果T是对对象类型的右价引用,则为xvalue否则,结果是一个pr值