One*_*ero -2 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;
}
Run Code Online (Sandbox Code Playgroud)
上面两个似乎只是在做同样的事情。那么为什么推荐使用移动构造函数呢?它提供了哪些优势?
使用正确的移动构造函数的原因有很多:
习俗。考虑以下代码:
Foo foo;
Foo bar(std::move(foo));
Run Code Online (Sandbox Code Playgroud)
如果您看到该代码,您将非常清楚您要做什么:您正在foo进入bar. 相比之下:
Foo foo;
Foo bar(&foo);
Run Code Online (Sandbox Code Playgroud)
这是什么意思?它是否存储指向另一个的指针Foo?是Foo某种链表节点类型吗?您必须在Foo基于指针的构造函数的文档中查找它。
您无法获得指向纯右值的指针。Foo bar(Foo{})将(C++17 之前)创建一个临时纯右值,然后从它移入bar(移动可以在 C++17 之前被省略)。但是你不能这样做:Foo bar(&Foo{}).
您可以从有意义的事物中获得自动移动。C++17 的广义省略使许多这些自动动作消失,但仍有一些:
Foo function()
{
Foo foo;
//Do stuff
return foo;
}
Run Code Online (Sandbox Code Playgroud)
这将从foo无需调用std::move. 原因是这foo是一个即将被销毁的局部变量。以这种方式返回它意味着从它移动到返回值是完全合理的。
您的方式需要明确地编写return &foo. 这使得auto返回类型推导变得相当困难。这样的函数会推导出 a Foo*,这意味着您刚刚返回了一个悬空指针。而如果你这样做return foo;,它会推导出一个Foo纯右值,并自动移动(可能会被忽略)。
不需要nullptr检查。如果您使用Foo*,则可能有人会传递空指针。而使用参考,则不太可能(而且他们已经调用了 UB)。
如果我们想要对现有语言结构的移动支持,我们只需使用非const引用来表示“移动”,而不是指针。通过给它自己的语法,明确什么时候我们在移动什么东西,什么时候我们不移动。
| 归档时间: |
|
| 查看次数: |
600 次 |
| 最近记录: |