如果我有一个管理一些动态内存的类(例如矢量类型)并且它已经有一个移动构造函数,为函数提供移动感知重载是否有意义,或者是否会移动 - 构造师会照顾它吗?
例如,我应该使用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
他们中的任何一个都失去了优化机会,因为我没有提供移动感知变体吗?
答案 0 :(得分:5)
Func1
和Func5
具有相同的签名,并且已经“移动感知”,因为可以使用左值或右值调用它们,并且可以在传递右值时构造参数。
Func3
和Func4
,使用Func(Class&&)
重载它们将是语义的重大变化,而不仅仅是优化。
Func7
已经可以用rvalues调用,没有什么可以通过复制或移动来初始化,重载它将毫无意义。
Func8
但执行副本,将该函数更改为Func8(Class)
将使用副本或移动初始化参数,具体取决于是使用左值还是右值调用它。或者,使用Func8(Class&&)
重载它也可以让你在传递右值时避免复制,但现在你有两个要维护的函数。
答案 1 :(得分:3)
首先,当然,你不应该为移动意识而烦恼 过载直到分析器显示它是必要的;它的 额外的复杂性,除非它,否则不应该引入 有必要的。
然而,假设分析器确实显示了复制 一个重大的开销:
Func1
(和Func5
,签名相同):这个
违反了大多数编码指南(即传递类对象)
参考const); 如果你使用这个签名,它就是
可能是因为您需要参数的唯一副本。移动
语义将给你一个独特的副本,所以他们可能会
合适的。
Func2
和Func3
暗示您要修改
客户的对象。所以你需要访问客户端的对象,
移动语义不会给你。
Func7
和Func8
是常见的情况。如果你只是
访问,而不需要自己存储副本,没有
指向移动语义;它可能会稍微慢一些
而不是对const的引用。如果您要存储副本,
然后移动语义可以产生显着的差异。