Foo(Foo&& other) {
this->bar = other.bar;
other.bar = nullptr;
}
Foo(Foo* other) {
this->bar = other->bar;
other->bar = nullptr;
}
以上两个似乎只是在做同样的事情。那么为什么建议使用移动构造函数呢?它提供了什么优势?使用移动构造函数与传递指针有什么优势?
Foo(Foo&& other) {
this->bar = other.bar;
other.bar = nullptr;
}
Foo(Foo* other) {
this->bar = other->bar;
other->bar = nullptr;
}
以上两个似乎只是在做同样的事情。那么为什么建议使用移动构造函数呢?它提供了什么优势?使用移动构造函数与传递指针有什么优势?
使用适当的转移构造的原因有很多:
公约。请看下面的代码:
Foo foo;
Foo bar(std::move(foo));
如果你看到代码,它是丰富清楚你想要做什么:你正在移动foo
为bar
。相比之下:
Foo foo;
Foo bar(&foo);
这是什么意思?它是否存储指向另一个Foo
的指针?是Foo
某种链接列表节点类型?您必须在Foo
的基于指针的构造函数的文档中查找它。
你不能得到一个指向prvalues的指针。 (pre-C++ 17)会创建一个临时值,然后从它移动到bar
(此举可能会在C++ 17之前被忽略)。但是你不能这样做:Foo bar(&Foo{})
。
你可以从有意义的事物中自动移动。 C++ 17的广义省音让许多的这些举动自动消失,但也有一些仍然存在:
Foo function()
{
Foo foo;
//Do stuff
return foo;
}
这将从foo
移动,而无需调用std::move
。原因是foo
是即将销毁的局部变量。以这种方式返回意味着从它转换到返回值是完全合理的。
你的方式需要明确写入return &foo
。这使得返回类型扣除auto
变得相当困难。这样的函数会推导出一个Foo*
,这意味着你刚刚返回了一个悬挂指针。而如果你做return foo;
,它会推导一个Foo
prvalue,并带有一个自动移动(可能会被忽略)。
无需nullptr
检查。如果你拿一个Foo*
,有人可能会传递一个空指针。而引用,这是不太可能的(他们已经调用UB)。
如果我们想移动与现有的语言结构的支持,我们会刚使用非const
引用意味着“移动”,而不是一个指针。通过赋予它自己的语法,在我们移动某个事物时以及当我们不移动时清楚地说明。
那么,对于初学者来说,你不能采用右值的地址...... – Brian
优点是移动构造函数将在适用的移动/复制上下文中自动使用。你的“指针”构造函数不会。 – AnT
另外,引用不能为空,但可以是一个指针,所以在交换之前你必须显式检查这个条件。 –