2017-01-28 44 views
-2
Foo(Foo&& other) { 
    this->bar = other.bar; 
    other.bar = nullptr; 
} 

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

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

+2

那么,对于初学者来说,你不能采用右值的地址...... – Brian

+2

优点是移动构造函数将在适用的移动/复制上下文中自动使用。你的“指针”构造函数不会。 – AnT

+0

另外,引用不能为空,但可以是一个指针,所以在交换之前你必须显式检查这个条件。 –

回答

4

使用适当的转移构造的原因有很多:

  1. 公约。请看下面的代码:

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

    如果你看到代码,它是丰富清楚你想要做什么:你正在移动foobar。相比之下:

    Foo foo; 
    Foo bar(&foo); 
    

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

  2. 你不能得到一个指向prvalues的指针。 (pre-C++ 17)会创建一个临时值,然后从它移动到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)。

如果我们想移动与现有的语言结构的支持,我们会刚使用非const引用意味着“移动”,而不是一个指针。通过赋予它自己的语法,在我们移动某个事物时以及当我们不移动时清楚地说明。

相关问题