为什么这需要一个明确的std :: move?

vda*_*ras 14 c++ c++11

假设我有一个Foo包含std::vectorstd::unique_ptr另一个类的对象构造的类,Bar.

typedef std::unique_ptr<Bar> UniqueBar;

class Foo {
    std::vector<UniqueBar> bars;
public:
    void AddBar(UniqueBar&& bar);
};

void Foo::AddBar(UniqueBar&& bar) {
    bars.push_back(bar);
}
Run Code Online (Sandbox Code Playgroud)

这导致编译错误(在g ++ 4.8.1中)说复制构造函数std::unique_ptr被删除,这是合理的.这里的问题是,因为bar参数已经是一个右值引用,为什么std::unique_ptr要调用复制构造函数而不是它的移动构造函数?

如果我明确地调用std::move,Foo::AddBar那么编译问题就会消失,但我不明白为什么需要这样做.我认为这是多余的.

那么,我错过了什么?

Die*_*ühl 16

基本上,每个具有名称的对象都是左值.当您使用右值引用将对象传递给函数时,该函数实际上会看到左值:它被命名.然而,右值引用的作用表明它来自一个准备传输的对象.

换句话说,右值参考是不对称的:

  • 他们只能接收rvalues,即临时对象,即将离开的对象,或看起来像是rvalues的对象(例如,结果std::move(o))
  • 然而,右值参考本身看起来像左值


Dav*_*eas 9

看起来很混乱,rvalue-reference绑定到rvalue,但用作表达式是左值.


jua*_*nza 8

bar实际上是一个左值,所以你需要传递它std::move,以便在调用时将其视为右值push_back.

Foo::AddBar(UniqueBar&& bar)超载只是确保当一个右值到一个调用传递这个重载拾取Foo::AddBar.但bar论证本身有一个名称,是一个左值.