3

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

T source();
sink(T);

// or

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

1 回答 1

3

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

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

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

编辑:确实,对于sink(T)不能有效移动的类型(使用基于值的实现的类型,即 ie std::array),这并不能很好地发挥作用,因为它需要一个(右值)引用可能会做的副本。甚至对于完全不移动的可移动类型仍然比移动更快(尽管这应该可以忽略不计)。但话又说回来,我认为,源和汇首先不能很好地与值实现类型配合使用。无论如何,在这种情况下T source(),在性能方面并不是一个好主意(但也不能T&& source()像上面描述的那样被替换)。

于 2012-12-21T10:15:03.457 回答