当第一个向量重新分配时,另一个向量内的std :: vectors会重新分配吗?

Ann*_*inn 19 c++ stl vector

我有一个矢量 std::vector<std::vector<ContactPairs>> m_contactPairs;

如果我调用m_contactPairs.push_back()或任何其他函数将调整最外层向量的大小,那么该向量内的元素是否必须重新分配(在这种情况下是内部元素std::vector<ContactPairs>),或者内部向量是否只做一个浅拷贝并保持指向同一个内存他们已经拥有?

我使用的是先前的C++ 11 Visual Studio 2010,但它具有一些扩展功能

Ral*_*zky 15

简短回答:这取决于您使用的标准和库实现:

  • 在C++ 98和C++ 03中没有任何移动,因此一切都将被深深复制,包括重新分配.
  • 在C++ 11和C++ 14中,将有一个深度副本,包括重新分配,或者,如果实现提供了一个noexcept移动构造函数std::vector<ContactPairs>.
  • 在即将到来的C++ 17中,内部向量将被移动,不会执行深度复制.

这是推理:

  1. 内部向量类型std::vector<ContactPairs>有一个移动构造函数,它noexcept根据即将推出的C++ 17标准(从N4296开始)而不是 noexcept根据C++ 11和C++ 14标准的[vector.modifiers]部分.你也可以在这里找到它.但是,即使符合C++ 11和C++ 14的实现也可以指定noexcept,因为实现可以提供比标准规定的更强的保证(参见C++标准17.6.5.12).但是,许多实现方法并没有这样做.

  2. 实施该std::vector<T>::push_back()方法需要保证强大的异常安全性,即如果它抛出则没有副作用.(参见C++标准,[container.requirements.general]部分§10或§11或此处.)

  3. 如果您调用的向量的新大小push_back()超出其容量,则需要为新位置分配内存,并且需要复制元素或将其移动到新位置.如果移动外部向量的元素可能失败(否noexcept),则需要复制元素以实现强异常保证.在这种情况下,内部向量的每个副本需要额外的分配.但是,如果移动noexcept,则整个移动循环不能抛出并且可以安全地用于实现强异常保证.

实施std::vector<T>移动建设与noexcept保证似乎是一件微不足道的事情std::vector.我怀疑,标准委员会可能会犹豫是否将此保证放入标准中以保持一致性:对于其他基于节点的容器,具有标记节点可能是有益的,即使对于默认构造也需要分配.由于移动后的容器需要在移动后有效,因此可能存在一个可能需要进行分配的分配std::list,例如.因此,无法noexcept保证移动构造函数std::list和其他基于节点的标准容器类型.


Dre*_*ann 9

在C++ 03中,std::vector重新分配将复制("深层复制")每个元素.这意味着对于您的情况,每个向量都将被复制.

在C++ 11或更高版本中,仅当元素具有移动构造函数时,std::vector重新分配才会移动每个元素.noexcept

Visual Studio 2010缺乏noexcept支持,因此您仍然可以获得深层复制.

  • **注意**:`std :: vector`移动操作**不保证是'noexcept`(库可以添加noexcept规范,但C++ 11和C++ 14不需要这个) ,这意味着它可能会或可能不会*移动*.(我希望库在他们*知道*他们可以时添加规范,这基本上取决于*allocator*) (3认同)
  • @RalphTandetzky:17.6.5.12*[...]实现可以通过添加非抛出noexcept-specification来强化非虚函数的异常规范* (3认同)