使用移动构造函数与传递指针有什么好处?

时间:2017-01-28 01:42:49

标签: c++ constructor move move-semantics

Foo(Foo&& other) {
  this->bar = other.bar;
  other.bar = nullptr;
}

Foo(Foo* other) {
  this->bar = other->bar;
  other->bar = nullptr;
}

以上两个似乎只是在做同样的事情。那么为什么建议使用移动构造函数呢?它提供了哪些优势?

1 个答案:

答案 0 :(得分:4)

使用正确的移动构造函数的原因很多:

  1. 公约。请考虑以下代码:

    Foo foo;
    Foo bar(std::move(foo));
    

    如果您看到该代码,那么 清楚了解您要尝试做的事情:您将foo移动到bar。相比之下:

    Foo foo;
    Foo bar(&foo);
    

    这是什么意思?它是否存储指向另一个Foo的指针? Foo是某种链表节点类型吗?您必须在Foo基于指针的构造函数的文档中查找。

  2. 您无法获得指向prvalues的指针。 Foo bar(Foo{})会(在C ++之前的17版本)创建一个临时值prvalue然后从它移动到bar(移动可以在C ++之前被省略17)。但是你不能这样做:Foo bar(&Foo{})

  3. 您可以从有意义的事物中自动移动。 C ++ 17的广义省略使许多这些自动移动消失了,但还有一些仍然存在:

    Foo function()
    {
      Foo foo;
      //Do stuff
      return foo;
    }
    

    这将从foo移出而无需致电std::move。原因是foo是一个即将被销毁的局部变量。以这种方式返回它意味着从它移动到返回值是完全合理的。

    您的方式需要明确撰写return &foo。而auto返回类型推导使事情变得相当困难。这样的函数会推导出Foo*,这意味着你只是返回了一个悬空指针。如果你做return foo;,它会推导Foo prvalue,并自动移动(可能会被省略)。

  4. 无需nullptr次检查。如果您使用Foo*,则可能会有人传递空指针。虽然有参考,但它更不可能(并且他们已经调用了UB)。

  5. 如果我们想要使用现有语言结构移动支持,我们只使用非const引用来表示"移动"而不是指针。通过赋予它自己的语法,在我们移动某些东西时以及当我们不移动时明确说明。