[英]Will std::vectors inside another vector reallocate when the first vector reallocates?
我有一個矢量std::vector<std::vector<ContactPairs>> m_contactPairs;
如果我調用m_contactPairs.push_back()
或任何其他將調整最外層向量的函數,那么該向量內的元素是否必須重新分配(在這種情況下內部元素是std::vector<ContactPairs>
),或者是內部向量只做一個淺拷貝並繼續指向他們已經擁有的相同內存?
我使用的是先前的C ++ 11 Visual Studio 2010,但它具有一些擴展功能
簡短回答:這取決於您使用的標准和庫實現:
noexcept
上的移動構造函數std::vector<ContactPairs>
這是推理:
內載體類型std::vector<ContactPairs>
具有移動構造,其是noexcept
根據即將到來的C ++ 17標准(如N4296的),而不是 noexcept
根據C ++ 11和C ++ 14個標准,部分[vector.modifiers]。 你也可以在這里找到它。 但是,即使符合C ++ 11和C ++ 14的實現也可以指定noexcept
,因為實現可以提供比標准規定的更強的保證(參見C ++標准17.6.5.12)。 但是,許多實現方法並沒有這樣做。
std::vector<T>::push_back()
是保證強異常安全性所必需的,即如果它拋出則沒有副作用。 (參見C ++標准,[container.requirements.general]部分§10或§11或此處 。)
如果調用push_back()
的向量的新大小超過其容量,則需要為新位置分配內存,並且需要復制元素或將其移動到新位置。 如果移動外部向量的元素可能失敗(沒有noexcept
),則需要復制元素以實現強異常保證。 在這種情況下,內部向量的每個副本都需要額外的分配。 但是,如果移動是noexcept
,則整個移動循環不能拋出並且可以安全地用於實現強異常保證。
使用noexcept
保證實現std::vector<T>
移動構造似乎對std::vector
是一件微不足道的事情。 我懷疑,標准委員會可能會猶豫是否將此保證放入標准中以保持一致性:對於其他基於節點的容器,具有標記節點可能是有益的,即使對於默認構造也需要分配。 由於移動后的容器需要在移動后有效,因此可能會有一個std::list
移動所需的分配,例如。 因此, std::list
和其他基於節點的標准容器類型的移動構造函數沒有noexcept
保證。
在C ++ 03中, std::vector
重新分配將復制 (“深層復制”)每個元素。 這意味着對於您的情況,每個向量都將被復制。
在C ++ 11或更高版本中, 僅當元素具有noexcept
的移動構造函數時, std::vector
重新分配才會移動每個元素。
Visual Studio 2010缺少noexcept
支持,因此您仍然可以獲得深層副本。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.