使用移动构造函数与传递指针有什么优势?
What's the advantage of using move constructor vs passing a pointer?
Foo(Foo&& other) {
this->bar = other.bar;
other.bar = nullptr;
}
Foo(Foo* other) {
this->bar = other->bar;
other->bar = nullptr;
}
以上两个似乎只是在做同样的事情。那么为什么建议使用move构造函数呢?它提供了什么优势?
使用正确的移动构造函数的原因有很多:
-
公约。考虑以下代码:
Foo foo; Foo bar(std::move(foo));
如果您看到该代码,就非常清楚您要做什么:您正在将
foo
移动到bar
。相比之下:Foo foo; Foo bar(&foo);
这是什么意思?它是否存储了指向另一个
Foo
的指针?Foo
是某种链表节点类型吗?您必须在文档中查找Foo
的基于指针的构造函数。 -
无法获取指向prvalues的指针。
Foo bar(Foo{})
将(在C++17之前)创建一个临时的prvalue,然后从它移动到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
引用来表示"移动",而不是指针。通过给它自己的语法,让它清楚地表明我们什么时候在移动,什么时候不在移动。
相关文章:
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 初始化或分配空字符串文字到指向 C 中的 char 的指针或指向 C++ 中 const char 的指针的原因是什么
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 使用基类指针调用基类的值构造函数的语法是什么?
- 将指针分配给另一个指针时会发生什么情况?
- 当该数组的索引中没有元素时,指针指向什么?
- C++:Lambda 函数指针转换的用例是什么?
- C++关于指针和使用函数将它们启动到堆的行为究竟是什么?
- 这个失败的测试是将零添加到空指针未定义的行为、编译器错误还是其他什么?
- 使用共享指针时,从共享指针本身释放内存的机制是什么
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 什么更好?返回对象指针列表?或返回指向对象列表的指针?
- 什么是更好的做法?通过指针或标识符传递类成员?
- 如果我在 const 函数上使用指针,我可以返回什么?
- 为什么此指针值不能转换为整数的规则是什么?
- 在自定义 std::vector-like 容器中处理指针和非指针模板类型的最佳方法是什么?
- 在什么情况下,需要共享智能指针而无法使用唯一指针?
- 以下与指针相关的代码的输出是什么?
- 指向数组基址的指针而不是指向第一个元素的指针有什么优点?
- C++:在向量中插入什么 - 指针或引用,矢量何时复制它的元素?