问题描述
由于我们在C ++中移动semantinc,现在通常要做
Since we have move semantincs in C++, nowadays it is usual to do
void set_a(A a) { _a = std::move(a); }
原因是如果 a
一个右值,副本将被省略,将只有一个移动。
The reasoning is that if a
is an rvalue, the copy will be elided and there will be just one move.
但是,如果 a
是一个左值,会发生什么?它似乎将有一个副本构造,然后一个移动分配(假设A有一个适当的移动赋值运算符)。如果对象具有太多的成员变量,则移动分配可能是昂贵的。
But what happens if a
is an lvalue? It seems there will be a copy construction and then a move assignment (assuming A has a proper move assignment operator). Move assignments can be costly if the object has too many member variables.
另一方面,如果我们做
void set_a(const A& a) { _a = a; }
只有一个副本分配。
推荐答案
我们可以说这种方式比通过值传递的习惯更好。移动类型在现代C ++使用中是罕见的。如果你担心移动的成本,写两个重载:
Expensive-to-move types are rare in modern C++ usage. If you are concerned about the cost of the move, write both overloads:
void set_a(const A& a) { _a = a; }
void set_a(A&& a) { _a = std::move(a); }
或完美转发设置者:
template <typename T>
void set_a(T&& a) { _a = std::forward<T>(a); }
将接受左值,右值和任何可隐式转换为 (_a)
,而不需要额外的副本或移动。
that will accept lvalues, rvalues, and anything else implicitly convertible to decltype(_a)
without requiring extra copies or moves.
尽管从左值设置时需要额外的移动,由于(a)绝大多数类型提供恒定时间移动,并且(b)复制和交换在单行代码中提供了异常安全性和接近最优的性能。
Despite requiring an extra move when setting from an lvalue, the idiom is not bad since (a) the vast majority of types provide constant-time moves and (b) copy-and-swap provides exception safety and near-optimal performance in a single line of code.
这篇关于pass-by-value-and-then-move构造一个坏习语?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!