当第一个向量重新分配时,另一个向量中的 std::vectors 会重新分配吗? [英] Will std::vectors inside another vector reallocate when the first vector reallocates?

查看:22
本文介绍了当第一个向量重新分配时,另一个向量中的 std::vectors 会重新分配吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个向量 std::vector>m_contactPairs;

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

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?

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

I'm using Visual Studio 2010, which is prior C++11, but has some of the functionality as extensions

推荐答案

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

Short answer: It depends on the standard you are using and the library implementation:

  • 在 C++98 和 C++03 中没有移动,因此所有内容都将被深度复制,包括重新分配.
  • 在 C++11 和 C++14 中,将有一个包含重新分配的深层副本,或者,如果实现在 std::vector< 的移动构造函数上提供了 noexcept;ContactPairs>.
  • 在即将到来的 C++17 中,内部向量将被移动,并且不会执行深度复制.
  • In C++98 and C++03 there is no move, hence everything will be deeply copied including a reallocation.
  • 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>.
  • In the upcoming C++17 the inner vector will be moved and no deep copy is performed.

原因如下:

  1. 内部向量类型 std::vector 有一个移动构造函数,它是 noexcept 根据即将到来的 C++17 标准(截至N4296) 和 not noexcept 根据 C++11 和 C++14 标准,[vector.modifiers] 部分.您还可以在此处找到此内容.但是,即使符合 C++11 和 C++14 的实现也可以指定 noexcept,因为实现可能提供比标准规定的更强大的保证(请参阅 C++ 标准 17.6.5.12).但是,许多实现还没有这样做.

  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]. 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). Many implemetations do not do that yet though.

std::vector::push_back() 的实现需要保证 强异常安全,i.e.如果它抛出没有副作用.(参见 C++ 标准,[container.requirements.general] §10 或 §11 或 这里.)

The implementation of the std::vector<T>::push_back() is required to guarantee strong exception safety, i. e. if it throws there are no side-effects. (See the C++ standard, section [container.requirements.general] §10 or §11 or here.)

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

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. 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. 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 保证实现 std::vector 移动构造对于 std::vector 来说似乎是一件微不足道的事情.我怀疑,为了一致性,标准委员会可能会犹豫是否将这种保证纳入标准:对于其他基于节点的容器,拥有哨兵节点可能是有益的,即使是默认构造也需要分配.由于移动后的容器需要在移动后有效,因此可能需要分配 std::list 移动,例如可能会抛出.因此,对于 std::list 和其他基于节点的标准容器类型的移动构造函数没有 noexcept 保证.

Implementing std::vector<T> move construction with the noexcept guarantee seems to be a trivial thing for 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. Hence, there's no noexcept guarantee for the move constructor of std::list and other node-based standard container types.

这篇关于当第一个向量重新分配时,另一个向量中的 std::vectors 会重新分配吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆