实现移动构造函数

时间:2014-12-18 21:42:54

标签: c++ c++11 move lvalue rvalue

在***评论的行中,为什么要调用Bar的复制构造函数? input_bar是一个右值引用,所以我希望调用move构造函数。它转换为左值参考吗?如果我将该行更改为bar_(std::move(input_bar)),我可以进行移动构造函数调用。

#include <iostream>
#include <array>
#include <memory>

class Bar
{
public:   
  Bar(const Bar& bar)
  {
    std::cout << "copy constructor called" << std::endl;
  }

  Bar(Bar&& bar)
  {
    std::cout << "move constructor called" << std::endl;
  }
};

class Foo
{
public:
  Foo(Bar&& input_bar) :
    bar_(input_bar) // ***
  {
  }
  Bar bar_;
};

int main()
{
  Bar bar;
  Foo foo(std::move(bar));
  return 0;
}

2 个答案:

答案 0 :(得分:9)

一旦实体有名字,它显然是一个左右!如果您有rvalue引用的名称,则名称为的实体为右值,但为左值。重点是你知道这个实体引用了一个右值,你可以合法地移动它的内容。

如果您想将右值转发到您调用的下一个函数,则可以使用std::move(),例如:

Foo(Bar&& bar): bar_(std::move(bar)) {}

没有std::move(),rvalue被认为是构造函数所有。使用std::move(),它会释放所有权并将其传递给下一个函数。

答案 1 :(得分:2)

你必须移动rhrs:

  Foo(Bar&& input_bar) :
    bar_(std::move(input_bar)) // ***
  {
  }

理由是,一旦我们实际使用RHR,它应该被人为地视为超出范围。强制您使用std::move允许以下代码未定义:

 Foo(Bar&& input_bar) {
    std::cout << input_bar.baz << std::endl;//not undefined
    bar_ = Bar{std::move(input_bar)};//input_bar is now essentailly destroyted
    //std::cout << input_bar.baz << std::endl;//Undefined behavior, don't do this
 }

一般的经验法则是,只有没有名字的东西实际上可以用作RHR ...... RHR作为参数有名字,因此将被视为LHR,直到你调用它们的函数。