这个帖子
Pass by value vs pass by rvalue reference的接受答案说:
For move-only types (as
std::unique_ptr
),pass-by-value seems to be the norm…
我有点怀疑.假设有一些不可复制的类型,Foo,也不便宜;和一些类型的酒吧,有一个成员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_; };
然后为以下代码:
Foo f; ... Bar bar(std::move(f));
构造函数(1)引发了2个移动结构,而构造函数(2)只引起了1.我还记得在Scott Meyers的有效现代C中阅读这个,但不记得哪个项目立即.
所以我的问题是,对于只移动类型(或者更一般来说,当我们想要转移参数的所有权时),我们不应该更喜欢通过rvalue引用以获得更好的性能?
更新:我知道传递值构造函数/赋值运算符(有时称为统一转换器/赋值运算符)可以帮助消除重复的代码.我应该说我对(1)性能很重要的情况更感兴趣,(2)类型是不可复制的,因此没有接受const lvalue引用参数的重复ctors /赋值操作符.
更新2:所以我找到了Scott Meyers关于具体问题的博客:http://scottmeyers.blogspot.com/2014/07/should-move-only-types-ever-be-passed.html.这个博客讨论了他在有效现代C的第41项中提倡的原因:
Consider pass by value only for copyable parameters…that are cheap to move…[and] always copied.
在该项目中有关于通过值与rvalue引用的广泛讨论,这里太多了.关键是,两种方式都有自己的优点和缺点,但是为了转移一个移动对象的所有权,通过rvalue引用似乎更可取.
解决方法
在这种情况下,我们可以吃蛋糕,吃饭.仅为Foo类型引用启用的模板构造函数使我们完美转发加上构造函数的单个实现:
#include <iostream> #include <utility> class Foo { public: Foo() {} Foo(const Foo&) = delete; Foo(Foo&&) { /* quite some work */ } }; class Bar { public: template<class T,std::enable_if_t<std::is_same<std::decay_t<T>,Foo>::value>* = nullptr> Bar(T&& f) : f_(std::forward<T>(f)) {} // (2) // Assuming only one of (1) and (2) exists at a time private: Foo f_; }; int main() { Foo f; Bar bar(std::move(f)); // this won't compile // Foo f2; // Bar bar2(f2); }