写一个在C11中持有STL容器的类的构造函数的最佳方式

前端之家收集整理的这篇文章主要介绍了写一个在C11中持有STL容器的类的构造函数的最佳方式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
class Foo {
  std::vector<SomeType> data_;
};

说Foo只能通过制作std :: vector< SomeType>的副本(技术上我的意思是复制或移动)目的.为Foo编写构造函数最好的方法是什么?

我的第一感觉是

Foo(std::vector<SomeType> data) noexcept : data_(std::move(data)) {};

使用它,实例的构造需要0或1次向量副本,具体取决于{data}的参数是否可移动.

解决方法

你的第一感觉是好的严格来说,这不是最佳的.但是它是如此接近最佳,你会有理由说你不在乎.

说明:

Foo(std::vector<SomeType> data) noexcept : data_(std::move(data)) {};

当客户端通过lvalue std :: vector< SomeType> 1复制将绑定到数据参数.然后1动作将“参数”复制到data_中.

当客户端传入一个xvalue std :: vector< SomeType> 1移动将绑定到数据参数.然后另一个动作将“参数”复制到data_中.

当客户端通过prvalue std :: vector< SomeType>移动将在绑定到数据参数时被消除.然后1动作将“参数”复制到data_中.

概要:

client argument    number of copies     number of moves
  lvalue                  1                   1
  xvalue                  0                   2
  prvalue                 0                   1

如果你这样做:

Foo(const std::vector<SomeType>&  data)          : data_(data) {};
Foo(      std::vector<SomeType>&& data) noexcept : data_(std::move(data)) {};

那么你有一个非常稍高的性能

当客户端通过lvalue std :: vector< SomeType> 1将复制参数到data_.

当客户端传入一个xvalue std :: vector< SomeType> 1将会将参数“复制”到data_中.

当客户端通过prvalue std :: vector< SomeType> 1将会将参数“复制”到data_中.

概要:

client argument    number of copies     number of moves
  lvalue                  1                   0
  xvalue                  0                   1
  prvalue                 0                   1

结论:

std :: vector移动构造非常便宜,特别是对于副本而言.

第一个解决方案将在客户端通过一个左值时花费额外的动作.这可能是在噪音级别,与必须分配内存的副本的成本相比.

当客户端通过xvalue时,第一个解决方案将会花费额外的动作.这可能是解决方案的一个弱点,因为它的成本增加了一倍.性能测试是唯一可靠的方法,以确保这是或不是一个问题.

当客户端通过prvalue时,这两个解决方案是相当的.

随着构造函数中的参数数量增加,第二个解决方案的维护成本呈指数增长.那就是每个参数需要const lvalue和rvalue的每个组合.这在1个参数(两个构造函数)中非常易于管理,在2个参数(4个构造函数)上较少,并且在此之后迅速变得无法管理(8个具有3个参数的构造函数).因此,最佳性能不是唯一关心的问题.

如果有许多参数,并且关注lvalue和xvalue参数的额外移动构造的成本,还有其他解决方案,但它们涉及相对较丑的模板元编程技术,许多人认为这太难以使用(我不,但我试图无偏见).

对于std :: vector,额外的移动构造的成本通常足够小,您将无法在整体应用程序性能中进行测量.

猜你在找的C&C++相关文章