我是新手在C++ 11中移动语义,我不太清楚如何处理unique_ptr
构造函数或函数中的参数.考虑这个引用自身的类:
#include <memory>
class Base
{
public:
typedef unique_ptr<Base> UPtr;
Base(){}
Base(Base::UPtr n):next(std::move(n)){}
virtual ~Base(){}
void setNext(Base::UPtr n)
{
next = std::move(n);
}
protected :
Base::UPtr next;
};
Run Code Online (Sandbox Code Playgroud)
这是我应该如何编写unique_ptr
参数的函数?
我需要std::move
在调用代码中使用吗?
Base::UPtr b1;
Base::UPtr b2(new Base());
b1->setNext(b2); //should I write b1->setNext(std::move(b2)); instead?
Run Code Online (Sandbox Code Playgroud) 我什么时候应该声明我的功能:
void foo(Widget w);
而不是
void foo(Widget&& w);
?
假设这是唯一的重载(例如,我选择一个或另一个,不是两个,也没有其他重载).没有涉及模板.假设该函数foo
需要所有权Widget
(例如const Widget&
,不是本讨论的一部分).我对这些情况范围之外的任何答案都不感兴趣.请参阅帖子末尾的附录,了解为什么这些约束是问题的一部分.
我和我的同事可以提出的主要区别是rvalue参考参数强制您明确复制副本.调用者负责制作一个显式副本,然后在std::move
需要副本时将其传入.在按值传递的情况下,隐藏了副本的成本:
//If foo is a pass by value function, calling + making a copy:
Widget x{};
foo(x); //Implicit copy
//Not shown: continues to use x locally
//If foo is a pass by rvalue reference function, calling + making a copy:
Widget x{};
//foo(x); //This would be a compiler error
auto copy = x; //Explicit copy
foo(std::move(copy));
//Not shown: continues …
Run Code Online (Sandbox Code Playgroud) 这个帖子的接受答案通过价值与通过右值参考传递说明:
对于仅移动类型(as
std::unique_ptr
),pass-by-value似乎是常态......
我对此有点怀疑.让我们说有一些不可复制的类型,Foo
移动也不便宜; 和一些Bar
有成员的类型Foo
.
class Foo {
public:
Foo(const Foo&) = delete;
Foo(Foo&&) { /* quite some work */ }
...
};
class Bar {
public:
Bar(Foo f) : f_(std::move(f)) {} // (1)
Bar(Foo&& f) : f_(std::move(f)) {} // (2)
// Assuming only one of (1) and (2) exists at a time
private:
Foo f_;
};
Run Code Online (Sandbox Code Playgroud)
然后为以下代码:
Foo f;
...
Bar bar(std::move(f));
Run Code Online (Sandbox Code Playgroud)
构造函数(1)引发2个移动构造,而构造函数(2)只引发1.我还记得在Scott Meyers的Effective Modern C++中读到这个但是不能立即记住哪个项目.
所以我的问题是,对于仅移动类型(或者更一般地说,当我们想要转移参数的所有权时),我们是否应该更倾向于通过rvalue-reference来获得更好的性能?
更新: …