本文介绍了pass-by-value-and-then-move构造一个坏习语?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于我们在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构造一个坏习语?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-01 16:56