![](/img/trans.png)
[英]Does std::vector::reserve guarantee that the implementation will not invalidate iterators in this case?
[英]Does std::vector::insert() invalidate iterators if the vector has enough room (created through reserve)?
回答如何自我復制載體? 使我對迭代器無效感到困惑。 一些文獻說:“如果使用insert,push_back等,則認為所有迭代器均無效”。 顯然,這可能會導致向量增長,從而使迭代器無效。 我知道會有足夠的空間怎么辦?
第一次嘗試:
myvec.reserve(myvec.size()*3); //does this protect me from iterator invalidation?
vector<string>::iterator it = myvec.end();
myvec.insert(myvec.end(), myvec.begin(), it);
myvec.insert(myvec.end(), myvec.begin(), it);
經過一些出色的回答后,請再次嘗試:
auto size = myvec.size();
myvec.reserve(size*3); //does this protect me from iterator invalidation?
myvec.insert(myvec.end(), myvec.begin(), myvec.begin()+size);
myvec.insert(myvec.end(), myvec.begin(), myvec.begin()+size);
經過更出色的回答后,第三次嘗試:
auto size = myvec.size();
myvec.reserve(size*3); //does this protect me from iterator invalidation?
back_insert_iterator< vector<string> > back_it (myvec);
copy (myvec.begin(),myvec.begin()+size,back_it);
copy (myvec.begin(),myvec.begin()+size,back_it);
引用自Josuttis的“ C ++標准庫參考”:
插入或刪除元素會使引用以下元素的引用,指針和迭代器無效。 如果插入導致重新分配,它將使所有引用,迭代器和指針無效。
建議我的代碼安全且行為明確。 標准中是否有段落可以保證這一點?
過去的迭代器總是有點特殊。 我會注意的 該標准說(23.3.6.5):
如果沒有發生重新分配,則插入點之前的所有迭代器和引用均保持有效。
此處的關鍵是“插入點之前”。 因為你原來it
不是將插入點之前(因為它是插入點),我不會行其上剩余的有效。
盡管確實可以做到,只要不超過容量,插入向量不會引起重新分配,並且不會使插入點之前的元素的迭代器無效(這可以說是end()
的情況,正如@KerrekSB指出的那樣) out),C ++ 11標准的表100(第23.2.3段a.insert(p,i,j)
為序列容器的a.insert(p,i,j)
函數指定了以下前提條件 :
[...] pre:i和j不是a的迭代器。 [...]
在您的情況下,它們顯然是,這使我認為程序具有未定義的行為。
迭代器不應在功能中間失效。 內存可能會被重新分配的想法不會成立,因為您不能在具有非平凡構造函數的對象上使用realloc
。 即使構造不是問題,在最壞的情況下,它仍然必須復制兩次初始序列,而在一般情況下,則沒有任何好處。
要點是,以這種方式實現它沒有任何意義; 不管標准怎么說,幾乎都可以確定alloc
, copy
, free
。
這是安全的,因為v.begin()
和v.end()
始終是最新的。
v.insert(v.end(), v.begin(), v.end());
v.insert(v.end(), v.begin(), v.end());
這不是。
vector<foo>::iterator i = v.begin();
vector<foo>::iterator j = v.end();
v.insert(v.end(), i, j);
v.insert(v.end(), i, j);
但是,自我插入可能會很不穩定。 在GCC下嘗試以下操作。 僅當有足夠的可用內存時,自我插入才會給出錯誤的結果(不確定這是否是錯誤)。
int main()
{
int position = 1, first = 2, last = 3;
// enforce error condition.
assert(position < first);
int size = 8;
// sanity check.
assert(first < last && last <= size);
std::vector<int> right, wrong;
// force resize during insertion.
right.reserve(size);
// avoid resize during insertion.
wrong.reserve(size + (last - first));
for ( int i = 0; i < size; i++ )
{
right.push_back(i);
wrong.push_back(i);
}
std::vector<int>::iterator i;
i = right.begin();
right.insert(i + position, i + first, i + last);
i = wrong.begin();
wrong.insert(i + position, i + first, i + last);
assert(right == wrong);
return 0;
}
注意:以上觀點專門適用於vector
,通常不適用於容器。 同樣,上述行為可能是錯誤的建議與標准無關,而是為vector
實現強大的自我插入的簡便性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.