什么时候我应该提供一个移动感知过载



如果我有一个管理一些动态内存的类(例如一个矢量类型的类),它已经有一个移动构造函数,它是否有意义提供一个移动感知的重载函数,或者将移动构造函数照顾它?

例如,我应该用Class&&变体重载其中哪一个(如果有的话):

// the move-aware overload for all of these would be
// void FuncX(Class&&);
void Func1(Class);
void Func3(Class&); // doesn't make a local copy
void Func4(Class&); // makes a local copy
void Func5(Class const);
void Func7(Class const&); // doesn't make a local copy
void Func8(Class const&); // makes a local copy

是否因为我没有提供移动感知变体而失去了优化机会?

Func1Func5具有相同的签名,并且已经具有"move-aware",因为它们可以用左值或右值调用,并且参数可以在传递右值时构造。

Func3Func4目前不能用右值调用,用Func(Class&&)重载它们将是语义上的重大变化,而不仅仅是优化。

Func7已经可以用右值调用了,没有什么可以通过复制或移动来初始化的,重载它是没有意义的。

Func8可以用右值调用,但执行复制,将该函数更改为Func8(Class)将使用复制或移动来初始化参数,这取决于它是用左值还是右值调用。或者,用Func8(Class&&)重载它也允许您在传递右值时避免复制,但是现在您有两个函数需要维护。

首先,当然,您不应该为移动感知而烦恼重载,直到分析器显示它是必要的;这是额外的复杂性,它不应该被引入,除非是必要的。

然而,假设分析器确实显示复制是显著的开销:

Func1(和具有相同签名的Func5): This违反了大多数编码准则(要求传递类对象)通过引用const);如果使用此签名,则为可能是因为您需要参数的唯一副本。移动语义会给你一个唯一的副本,所以它们可能是合适。

Func2Func3暗示您将修改客户的对象。所以你需要访问客户端的对象,这是移动语义不能给你的。

Func7Func8是通常的情况。如果你只是访问,不需要自己存储副本,没有移动点语义;它可能会稍微慢一些而不是对const的引用。如果你要存储副本,那么移动语义可以产生显著的差异。

最新更新