根据核心准则:
F.18:对于“ will-move-from”参数,请传递X &&和std :: move参数
示例为:
void sink(vector<int>&& v) { // sink takes ownership of whatever the argument owned
// usually there might be const accesses of v here
store_somewhere(std::move(v));
// usually no more use of v here; it is moved-from
}
我注意到,除了廉价复制(我几乎总是只考虑原语)之外,我倾向于对所有对象使用智能指针。因此,我几乎总是使用以下准则:
void sink(std::unique_ptr<OtherThanPrimitive> p) {
// use p ... possibly std::move(p) onward somewhere else
} // p gets destroyed
我开始考虑是否使用最佳实践。我可以想到的第一种方法的优点是,强制函数的调用者显式地std :: move,这使代码更简洁。在第二种方法中,移动构造函数将被调用两次,但是对于智能指针而言,这并不是一个大代价。考虑到上述问题,我开始考虑改变习惯,始终对第一个方法使用第一种方法,以确保可以支持移动(因此,大多数STL集合)。自定义对象的第二种方法(我假设考虑为类编写自定义移动构造函数的成本超过了可读性的收益)。有没有涵盖这一点的最佳实践?您通常采用哪种方法?我在理由中缺少什么吗?
答案 0 :(得分:0)
我可以认为第一种方法的优点是强制函数的调用者显式地std :: move,这使代码更简洁。在第二种方法中,移动构造函数将被调用两次,但是对于智能指针而言,这并不是一个大代价。
在void sink(T&&)
和void sink(T)
之间:都需要std::move
用于仅移动类型或调用move构造函数。给定可复制的左值参数,第二种形式也可以复制。如果复制T
并不便宜,那么静默获取副本可能是不利的。与第一种方法相比,即使与仅移动类型一起使用,第二种形式也将在函数参数中有额外的移动。如果T
移动起来并不便宜,那么这可能是一个不利条件。当移入数据成员或以其他方式在逻辑上复制自变量时,第二种形式允许一种重载同时接受T &&和const T&自变量,而不是每个重载都具有一个重载,然后对N个自变量具有2 ^ N个重载。 / p>
但是,第二种形式无条件地从参数移开。第一个可以有条件地从参数移开,也可以完全不从参数移开。呼叫者无法告知(不好!)。第二种形式提供了更清晰的意图表达。
请注意,问题526具有一个不错的辅助功能copy
,您可以将其与第一种形式一起使用,以用于价格不太便宜的可复制类型,从而使副本明确。使用该帮助程序,您可以在默认情况下以最少的移动次数移动,并选择加入显式副本。与第二种形式相比,签名仍然提供了较不清晰的意图。
考虑到上述问题,我开始考虑改变习惯,始终对我确信支持移动的集合(因此大多数STL集合)使用第一种方法。自定义对象的第二种方法
我认为自定义对象与支持移动的集合不是正确的区别。如果T
不可移动,则参数应为const T&
或T
(如果要复制)。在这种情况下,使用第一种形式是没有意义的。
根据经验,如果T
是可移动的,请使用核心准则。使用第一种形式。如果T
的价格便宜,请使用第二种形式。
我假设考虑为类编写自定义move构造函数的成本超过了可读性的收益
大多数类不必编写自定义的移动构造函数。东西拥有存储空间。这需要一个自定义的move构造函数。指向存储的内部簿记产生了对自定义move构造函数的需求。因此,容器。而且,如果您要编写一个带有提供的类型的通用容器,那么如果它可能更有效,就应该编写一个move构造函数。否则可能会更令人惊讶。