簡體   English   中英

為什么vector :: pop_back使迭代器(end()-1)無效?

[英]Why does vector::pop_back invalidate the iterator (end() - 1)?

注意:該問題也適用於erase 見底部。


vector上調用pop_back之后, end() - 1迭代器無效的事實背后的原因是什么?

為了澄清,我指的是這種情況:

std::vector<int> v;
v.push_back(1);
v.push_back(2);

std::vector<int>::iterator i1 = v.begin(), i2 = v.end() - 1, i3 = v.begin() + 1;

v.pop_back();

// i1 is still valid
// i2 is now invalid
// i3 is now invalid too

std::vector<int>::iterator i4 = v.end();

assert(i2 == i4);  // undefined behavior (but why should it be?!)
assert(i3 == i4);  // undefined behavior (but why should it be?!)

為什么會這樣? (即,這種失效何時將證明對實施有利?)

(請注意,這不僅是理論上的問題。如果您將_ITERATOR_DEBUG_LEVEL設置為2 ,則在嘗試以調試模式執行此操作時,Visual C ++ 2013-可能還有2012-也會顯示錯誤。)


關於erase

請注意,相同的問題也適用於erase
為什么erase(end() - 1, end())使end() - 1無效?

(因此,請不要說pop_back使end() - 1無效,因為它等效於調用erase(end() - 1, end()) ;這只是在問這個問題。)

有趣的問題是,使迭代器無效意味着什么。 而且我的標准確實沒有很好的答案。 我所知道的是,在某種程度上,該標准將迭代器視為不是指向容器內部位置的指針,而是作為駐留在容器中的特定元素的代理。

考慮到這一點,在刪除向量中間的單個元素之后,移除點之后的所有迭代器都將變得無效,因為它們不再引用之前引用的相同元素。

對這種推理的支持來自容器中其他操作的迭代器無效子句。 例如,在insert ,該標准保證,如果沒有重新分配,則插入點之前的迭代器仍然有效。 例外情況插入點之后 ,它將使所有迭代器無效。

如果迭代器的有效性僅與容器中存在迭代器所指向的元素有關,則該操作都不會使迭代器無效(同樣,在沒有重新分配的情況下)。

進一步講,如果您將迭代器有效性視為指針有效性 ,則在erase操作期間,向量中的所有迭代器都不會失效。 end()-1迭代器將變得不可取,但可以保持有效,事實並非如此。

pop_back通常是用pop_back erase(end()-1, end())

當您從向量中擦除一定范圍的迭代器時,從第一個被擦除和向前擦除的所有迭代器都將失效。 這包括一個范圍。

通常,有效的不可重新引用的非輸入迭代器始終引用相同的數據“位置”,直到無效為止。 erase的情況下,之后所有非無效的迭代器當前都具有相同的值位置。

上面兩個規則都必須進行修改才能獲得所需的行為。 第一個類似“除非您這樣做會刪除最后一個元素,在這種情況下,第一個被刪除的元素將成為最后一個迭代器”。 而且仍然有效的迭代器將變得不可取,據我所知,對於迭代器而言,這可能是唯一的狀態更改,在C ++中尚無先例。

成本既是標准中用來支付您要求的行為的額外技巧,又是嚴格的迭代器的健全性檢查。 好處-好吧,我看不到:在每種情況下,您都必須確切地知道發生了什么(一個非常特殊的迭代器只是在末尾成為一個迭代器而不是被無效),如果您知道是這種情況,只能說說end

並且需要單詞。 當你調用erase( a, b )從每一個迭代a上都會有其狀態以某種方式改變( *a不會返回相同的值,以及如何必須指定的更改)。 C ++采取了簡單的方法,只是聲明其狀態被erase更改的每個迭代器都將變為無效,並且使用它是未定義的行為:這允許實現者獲得最大的自由度。

從理論上講,它還可以進行優化。 如果在erase操作之前和之后取消引用迭代器,則可以認為您獲得的值是相同的! (假設不可能在對象析構函數內對容器進行間接修改,這也可以被證明)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM