C++11 按值传递和按右值传递引用的重载

C++11 按值传递和按右值传递引用的重载,c++11,parameter-passing,move-semantics,rvalue-reference,C++11,Parameter Passing,Move Semantics,Rvalue Reference,我有两个子程序重载,它接受一个类型的参数,该参数占用了数兆的动态内存,并且有一个移动构造函数和赋值运算符: // Version intended for use when we the caller has // deliberately passed an rvalue reference using std::move void MyClass::setParameter(MyMoveableType &&newParameter) { m_theLocalPar

我有两个子程序重载,它接受一个类型的参数,该参数占用了数兆的动态内存,并且有一个移动构造函数和赋值运算符:

// Version intended for use when we the caller has 
// deliberately passed an rvalue reference using std::move
void MyClass::setParameter(MyMoveableType &&newParameter)
{
    m_theLocalParameter = std::move(newParameter);
}

// Version intended for use when the caller has passed
// some other type of value which shouldn't be moved
void MyClass::setParameter(MyMoveableType newParameter) 
{
    m_theLocalParameter = std::move(newParameter);
}
很明显,第一个重载将newParameter的内容从子例程调用newParameter对象的链的上游移动,而第二个重载将创建newParameter的全新副本(或在适当的情况下调用复制省略以避免这样做,例如参数实际上是函数的返回值),然后将副本移动到本地数据成员中,从而避免进一步的副本

但是,如果我尝试使用第一个重载将对象移动到类中:

{
    MyClass        theDestination;
    MyMoveableType theObject
    ...
    // ...Various actions which populate theObject...
    ...

    TheDestination.setParameter(std::move(theObject));
    ...
}
…然后,在我尝试过的每个编译器上,我都会遇到如下错误:

call to member function 'setParameter' is ambiguous
现在我可以看到,将右值引用传递给第二个重载实际上是完全合法的,而且如果我没有提供第一个重载,我希望编译器在不发出警告的情况下会这样做。即使如此,我希望编译器完全清楚这段代码的意图,因此我希望它会这样做选择第二个重载作为最佳匹配

我可以通过重新定义第二个构造函数以获取const引用并删除std::move来消除这个错误(尽管这样做不会出错) 保留它;编译器会忽略它)。这可以正常工作,但我会失去利用复制省略的机会。这可能是 对于该特定应用程序而言,在性能方面具有重要意义;讨论的对象是以30秒的速度传输的高分辨率视频帧 每秒帧数

在这种情况下,我能做些什么来消除重载的歧义,从而使我的例程同时有一个pass-by-value和pass-by-rvalue引用版本

很明显,第一个重载将newParameter的内容从子程序调用newParameter对象的链的上游移动,而第二个重载将创建一个全新的副本

这并不是你真正要做的。你有两个明智的选择:

接近A 您只需编写值重载,然后无论如何都要从中移动—这意味着您将始终支付构造函数的代价,要么移动,要么复制

方法B 您可以为
(const T&)
(T&&)
编写重载。这样,您可以在第一个文件中复制,并使用完美转发跳过第二个文件中的移动



我建议默认使用方法A,只有在c-tor调用实际上非常重要时才使用方法B。

谢谢。我觉得令人失望的是,该语言实现了诸如复制省略和移动语义等有用功能,然后阻止它们一起使用!有点像一手给予,另一手拿走。你能给m吗更多关于为什么推荐方法
A
而不是B的详细信息?这只是因为使用方法
A
只需编写值重载?@Vasilly.Prokopyev对于新手来说,它更简短、更容易阅读。你能解释为什么函数调用不明确吗?:)@BaranKarakus是的,这正是发生的事情。你知道为什么函数调用是不明确的吗?我有一个类似的问题,无法解释为什么我们在这里有歧义。我本以为只要参数是右值,就会调用第二个函数,否则就会调用第一个函数。