C++11 将一个向量移动到另一个向量 - 将右值引用传递给构造函数

C++11 moving one vector to another - passing an rvalue reference to a constructor

我正在尝试理解 C++ 移动语义、std::move() 和右值引用。

我已经实现了这个例子。

#include <iostream>
#include <vector>

int main()
{
  int totalSize = 6;

  std::vector<double> oldData{ 10, 20, 30 }; 

  oldData.resize(totalSize, 0);

  std::vector<double> newData(std::move(oldData));
  return 0;
}

我想知道这实际上是在将矢量 oldData 移动到 newData 还是在幕后进行复制。

假设您将无限循环修复为:

  for(unsigned i = 0; i < totalSize - oldData.size(); ++i)
    oldData.push_back(0);

然后这样写:

  for(unsigned i = oldData.size(); i < totalSize; ++i)
    oldData.push_back(0);

或者,甚至更好:

  oldData.resize(totalSize, 0);

然后 std::move 会将所有数据从 oldData 移动到 newData。这是 a quote from cppreference:

6) Move constructor. Constructs the container with the contents of other using move semantics. Allocator is obtained by move-construction from the allocator belonging to other. After the move, other is guaranteed to be empty().

7) Allocator-extended move constructor. Using alloc as the allocator for the new container, moving the contents from other; if alloc != other.get_allocator(), this results in an element-wise move. (in that case, other is not guaranteed to be empty after the move)

在您的特定情况下,向量有一个默认分配器,这意味着只有第 (6) 项适用。然而,如果有人传递了一个分配器,那么事情就会变得更有趣。

这是关于 复杂性 的 cppreference 的其余部分:

6) Constant.

7) Linear if alloc != other.get_allocator(), otherwise constant.

同样,在您的情况下,复杂度为 O(1),但使用分配器后事情会变得更有趣。

结论:内部表示必须在O(1) 中移动固定数量的指针,而不是一个一个地移动元素。可以使用具有容量和大小整数的一个指针或三个指针(容量的开始、结束和结束)来实现向量。对于所有这些实现,移动只是简单地使用指针。

但是,如果提供了非默认分配器并且两个向量使用不同的分配器对象,则必须逐个移动或复制这些值。