如何获取右值参考参数并将其传递给其他地方?

时间:2016-12-18 19:14:40

标签: c++ c++11 move-semantics

我是一个相当称职的C ++用户(不是一个完整的菜鸟)。我有一个充当资源句柄的类。这个类有一个移动构造函数和复制construtor被删除是有道理的:

struct Foo {

  Foo (int i) : // For sake of example.
    x(i)
  {}

  Foo (Foo && f) :
    x(f.x)
  {
    f.x = 0; // 0 is special and means "moved from".
  }

  Foo (const Foo & f) = delete;

private:
  int x;
};

我现在已经以货物崇拜的方式做了很多年,现在工作正常。现在我正试图用我的C ++ 11使用它。

我有另一个类vector Foo

struct Bar { // (Constructor added below)
  std::vector<Foo> foos;
};

我想为Bar编写一个构造函数,调用者在vector<Foo>中传递。我希望调用者提供的整个向量被移动到Bar.foos。我想通过使构造函数参数为vector<Foo>&&而不是普通vector<Foo>&来使调用者明确表示。这样,调用者必须std::move向量构造函数。

int main (int argc, char ** argv)
{     
    Foo f1 (1);
    Foo f2 (2);
    std::vector<Foo> v;
    v.push_back (std::move(f1));
    v.push_back (std::move(f2));

    Bar b (std::move(v)); // I want the user to HAVE TO std::move v.
    return 0;
}

我天真地试着像这样编写Bar构造函数:

struct Bar {

  Bar (vector<Foo> && vf) :
    foos (vf) // pass the rvalue reference into foos' constructor, right?
  {}

  std::vector<Foo> foos;
};

我的电脑有g ++ 4.9.2和clang ++ 3.5.0,它们都给我一小部分错误。他们都试图使用向量复制构造函数构造Bar.foos,然后失败,因为我删除了Foo的复制构造函数。

如何将vector<Foo>的右值引用'vf'直接赋予'foos'的构造函数?

2 个答案:

答案 0 :(得分:8)

命名参数不是右值,因此您必须通过调用vfstd::move转换为右值参考:

Bar(std::vector<Foo>&& vf) : foos(std::move(vf) {}

另外,如果用户必须调用std::move来获取rvalue参数,那就不正确了。当参数是函数的返回值时,不需要std::move,这是rvalue的经典概念。

答案 1 :(得分:0)

通常,如果您有一个仅移动类型的参数,则按值:

struct Bar
{
    std::vector<Foo> foos;

    Bar(vector<Foo> vf) :
        foos(std::move(vf)a) {}
};

这会强制调用者编写

Bar x(std::move(y));

明确表示y的所有权已被放弃。 此外,调用者只需传递函数的返回值,而无需进一步调整:

Bar x(get_me_some_Foos());