簡體   English   中英

為什么std :: vector :: insert會在插入點之后使所有迭代器無效

[英]Why does std::vector::insert invalidate all iterators after the insertion point

insertstd::vector ,C ++標准確保插入點之前的所有迭代器保持有效,只要capacity沒有用完(參見[23.2.4.3/1]或std :: vector iterator invalidation )。

在插入點保持有效(如果容量沒有用盡)之后不允許迭代器的原因是什么? 當然,然后他們會指向一個不同的元素,但是(從std::vector的假定實現),仍然可以使用這樣的迭代器(例如取消引用它或遞增它)。

您似乎在想一個“無效”迭代器,因為只有一個會在使用時引發崩潰,但標准的定義更廣泛。 它包括迭代器仍然可以安全地解除引用的可能性,但不再指向它預期指向的元素。 (這是觀察的特殊情況,“未定義的行為” 並不意味着“您的程序將立即崩潰”;它也可能意味着“您的程序將默默地計算錯誤的結果”,甚至“在實現中不會發生任何明顯的錯誤” “。)

更容易證明為什么這是erase問題:

#include <vector>
#include <iostream>
int main(void)
{
    std::vector<int> a { 0, 1, 2, 3, 4, 4, 6 };

    for (auto p = a.begin(); p != a.end(); p++) // THIS IS WRONG
        if (*p == 4)
            a.erase(p);

    for (auto p = a.begin(); p != a.end(); p++)
        std::cout << ' ' << *p;

    std::cout << '\n';
}

在C ++的典型實現中,這個程序不會崩潰,但它會打印0 1 2 3 4 6 ,而不是0 1 2 3 6 ,因為可能會打算刪除前4 無效的 p - 通過在第二個4推進它。

您的C ++實現可能有一個特殊的“調試”模式,在該模式下,該程序在運行時崩潰。 例如,使用GCC 4.8:

$ g++ -std=c++11 -W -Wall test.cc && ./a.out
 0 1 2 3 4 6

$ g++ -std=c++11 -W -Wall -D_GLIBCXX_DEBUG test.cc && ./a.out
/usr/include/c++/4.8/debug/safe_iterator.h:307:error: attempt to increment 
    a singular iterator.

Objects involved in the operation:
iterator "this" @ 0x0x7fff5d659470 {
type = N11__gnu_debug14_Safe_iteratorIN9__gnu_cxx17__normal_iteratorIPiNSt9__cxx19986vectorIiSaIiEEEEENSt7__debug6vectorIiS6_EEEE (mutable iterator);
  state = singular;
  references sequence with type `NSt7__debug6vectorIiSaIiEEE' @ 0x0x7fff5d659470
}
Aborted

請理解該程序無論如何都會引發未定義的行為。 只是在調試模式下,未定義行為的后果更為顯着。

向量會動態增長,因此當您按下向量時,如果項目沒有空間,則需要為其分配內存。 標准要求vector必須將其元素存儲在連續的內存中,因此在分配內存時,必須足以存儲所有現有元素和新元素。

向量不知道自身的任何迭代器,因此無法將它們更新為新的元素存儲。 因此,在重新分配內存后,迭代器無效。

迭代器可能引用不同的元素就足以使它們失效。 迭代器應該在其有效生命周期的持續時間內引用相同的元素。

你是對的,在實踐中,如果你要取消引用這樣的迭代器,你可能不會遇到任何崩潰或鼻子惡魔,但這並不能使它有效。

向量不知道哪些迭代器存在。 然而,插入元素后元素的內存位置發生了變化。 這意味着,需要更新迭代器以反映它們保持有效的更改。 但是向量無法執行此更新,因為它不知道存在哪些迭代器。

暫無
暫無

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

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