[英]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: 简短回答:这取决于您使用的标准和库实现:
noexcept
on the move constructor of std::vector<ContactPairs>
. 在C ++ 11和C ++ 14会有包括重新分配的深层副本,或者,如果该实现提供了noexcept
上的移动构造函数std::vector<ContactPairs>
And here's the reasoning: 这是推理:
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. 但是,许多实现方法并没有这样做。
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或此处 。)
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.