简体   繁体   English

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

[英]Will std::vectors inside another vector reallocate when the first vector reallocates?

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

If I call m_contactPairs.push_back() or any other function that will resize the outermost vector, will the elements inside that vector have to reallocate (the inner elements in this case being std::vector<ContactPairs> ), or will the inner vectors just do a shallow copy and keep pointing at the same memory they already own? 如果我调用m_contactPairs.push_back()或任何其他将调整最外层向量的函数,那么该向量内的元素是否必须重新分配(在这种情况下内部元素是std::vector<ContactPairs> ),或者是内部向量只做一个浅拷贝并继续指向他们已经拥有的相同内存?

I'm using Visual Studio 2010, which is prior C++11, but has some of the functionality as extensions 我使用的是先前的C ++ 11 Visual Studio 2010,但它具有一些扩展功能

Short answer: It depends on the standard you are using and the library implementation: 简短回答:这取决于您使用的标准和库实现:

  • In C++98 and C++03 there is no move, hence everything will be deeply copied including a reallocation. 在C ++ 98和C ++ 03中没有任何移动,因此一切都将被深深复制,包括重新分配。
  • In C++11 and C++14 there will be a deep copy including a reallocation, or, if the implementation provides a noexcept on the move constructor of std::vector<ContactPairs> . 在C ++ 11和C ++ 14会有包括重新分配的深层副本,或者,如果该实现提供了noexcept上的移动构造函数std::vector<ContactPairs>
  • In the upcoming C++17 the inner vector will be moved and no deep copy is performed. 在即将到来的C ++ 17中,内部向量将被移动,不会执行深度复制。

And here's the reasoning: 这是推理:

  1. The inner vectors type std::vector<ContactPairs> has a move constructor which is noexcept according to the upcoming C++17 standard (as of N4296) and not noexcept according to the C++11 and C++14 standards, section [vector.modifiers]. 内载体类型std::vector<ContactPairs>具有移动构造,其是noexcept根据即将到来的C ++ 17标准(如N4296的),而不是 noexcept根据C ++ 11和C ++ 14个标准,部分[vector.modifiers]。 You can also find this here . 你也可以在这里找到它。 However, even C++11 and C++14 compliant implementations may specify noexcept , since implementations may provide stronger guarantees than prescribed by the standard (see C++ Standard 17.6.5.12). 但是,即使符合C ++ 11和C ++ 14的实现也可以指定noexcept ,因为实现可以提供比标准规定的更强的保证(参见C ++标准17.6.5.12)。 Many implemetations do not do that yet though. 但是,许多实现方法并没有这样做。

  2. The implementation of the std::vector<T>::push_back() is required to guarantee strong exception safety , ie if it throws there are no side-effects. std::vector<T>::push_back()是保证强异常安全性所必需的,即如果它抛出则没有副作用。 (See the C++ standard, section [container.requirements.general] §10 or §11 or here .) (参见C ++标准,[container.requirements.general]部分§10或§11或此处 。)

  3. If the new size of the vector on which you call push_back() exceeds its capacity, then memory needs to be allocated for the new spot and the elements need to be copied or moved to the new spot. 如果调用push_back()的向量的新大小超过其容量,则需要为新位置分配内存,并且需要复制元素或将其移动到新位置。 If moving the elements of the outer vector can fail (no noexcept ), then the elements need to be copied in order to implement the strong exception guarantee. 如果移动外部向量的元素可能失败(没有noexcept ),则需要复制元素以实现强异常保证。 In this case, each copy of an inner vector does require an additional allocation. 在这种情况下,内部向量的每个副本需要额外的分配。 However, if moving is noexcept , then the whole moving-in-a-loop cannot throw and is safe to use to implement the strong exception guarantee. 但是,如果移动是noexcept ,则整个移动循环不能抛出并且可以安全地用于实现强异常保证。

Implementing std::vector<T> move construction with the noexcept guarantee seems to be a trivial thing for std::vector . 使用noexcept保证实现std::vector<T>移动构造似乎对std::vector是一件微不足道的事情。 I suspect, the standards committee might have been hesitant to put this guarantee into the standard for consistency's sake: For other node-based containers it can be beneficial to have sentinel nodes, which require an allocation even for default construction. 我怀疑,标准委员会可能会犹豫是否将此保证放入标准中以保持一致性:对于其他基于节点的容器,具有标记节点可能是有益的,即使对于默认构造也需要分配。 Since the moved-from container needs to be valid after the move, there might be an allocation necessary for an std::list move which might throw, for example. 由于移动后的容器需要在移动后有效,因此可能会有一个std::list移动所需的分配,例如。 Hence, there's no noexcept guarantee for the move constructor of std::list and other node-based standard container types. 因此, std::list和其他基于节点的标准容器类型的移动构造函数没有noexcept保证。

In C++03, a std::vector reallocation will copy ("deep copy") each element. 在C ++ 03中, std::vector重新分配将复制 (“深层复制”)每个元素。 That means for your situation, each vector would be copied. 这意味着对于您的情况,每个向量都将被复制。

In C++11 or later, a std::vector reallocation will move each element only if the elements have a move constructor that is noexcept . 在C ++ 11或更高版本中, 仅当元素具有noexcept的移动构造函数时, std::vector重新分配才会移动每个元素。

Visual Studio 2010 lacks noexcept support, so you would still get a deep copy. Visual Studio 2010缺少noexcept支持,因此您仍然可以获得深层副本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM