具有移动语义的源和宿函数的签名

时间:2012-12-21 09:42:02

标签: c++ c++11 move-semantics

在编写源函数和接收函数时,我应该使用哪些签名来从移动语义中获益?为什么?

T source();
sink(T);

// or

T&& source();
sink(T&&);

1 个答案:

答案 0 :(得分:3)

嗯,考虑到源创建并返回一个新对象,T&& source()绝对是垃圾。不要从函数返回对局部变量的引用,此规则对rvalue引用应用相同的值,因为它始终应用于左值引用。

使用sink(T&&)是一个品味问题。它不是看起来干净和简化,但另一方面,它更明确地强调了函数的接收器本质,并且强制移动,即使对于可能也被复制的类型。但是,如果T应该是一个不可复制的类型(如std::unique_ptr),我更喜欢sink(T),因为它看起来更干净,并且明确表示移动无论如何,通过该类型的不可复制性。

但是,在所有情况下,你都会受益于移动语义,这是他们的优势之一,它们可以很好地集成到现有的代码中。因此,无论T t = source();具有哪个签名,sink(std::move(t));都将移动sink。只是sink(T)不会阻止您使用sink(t);而不是sink(std::move(t));来为可复制类型调用它,而后者又不会使用移动语义。但这是一个完全不同的问题,因为无论如何在适当的时候使用std::move应尽快学会成语。

编辑:确实,sink(T)对于不能有效移动的类型(使用基于值的实现的类型,即std::array)不能很好地发挥作用,因为它需要一个(rvalue)引用可能会做的副本。即使对于可移动的类型,根本不移动仍然比移动更快(尽管这应该是可以忽略的)。但是,我认为,首先,源和汇不能很好地与价值实施类型相媲美。在这种情况下T source()无论如何都不是那么好的想法(但是如上所述它也不能被T&& source()取代)。