簡體   English   中英

C++ STL 中的 const_iterator 和非常量迭代器有什么區別?

[英]What is the difference between const_iterator and non-const iterator in the C++ STL?

const_iteratoriterator之間有什么區別,你會在哪里使用一個而不是另一個?

const_iterator不允許您更改它們指向的值,常規iterator可以。

與 C++ 中的所有內容一樣,總是更喜歡const ,除非有充分的理由使用常規迭代器(即您想使用它們不是const來更改指向值的事實)。

它們應該是不言自明的。 如果 iterator 指向類型為 T 的元素,則 const_iterator 指向類型為“const T”的元素。

它基本上等同於指針類型:

T* // A non-const iterator to a non-const element. Corresponds to std::vector<T>::iterator
T* const // A const iterator to a non-const element. Corresponds to const std::vector<T>::iterator
const T* // A non-const iterator to a const element. Corresponds to std::vector<T>::const_iterator

const 迭代器總是指向同一個元素,所以迭代器本身是 const 的。 但是它指向的元素不一定是const,所以它指向的元素是可以改變的。 const_iterator 是指向 const 元素的迭代器,因此雖然迭代器本身可以更新(例如遞增或遞減),但它指向的元素不能更改。

不幸的是,STL 容器的很多方法都使用迭代器而不是const_iterator作為參數。 所以如果你有一個const_iterator ,你不能說“在這個迭代器指向的元素之前插入一個元素”(在我看來,說這樣的事情在概念上並不是const違規)。 如果您無論如何都想這樣做,則必須使用std::advance()boost::next()將其轉換為非常量迭代器。 例如。 boost::next(container.begin(), std::distance(container.begin(), the_const_iterator_we_want_to_unconst)) 如果容器std::list ,則該調用的運行時間將為O(n)

因此,在“合乎邏輯”的地方添加 const 的通用規則在 STL 容器方面不太通用。

但是,boost 容器采用 const_iterators(例如 boost::unordered_map::erase())。 因此,當您使用 boost 容器時,您可能會變得“具有攻擊性”。 順便說一句,有誰知道 STL 容器是否或何時修復?

盡可能使用const_iterator ,在別無選擇時使用iterator

最小的可運行示例

非常量迭代器允許您修改它們指向的內容:

std::vector<int> v{0};
std::vector<int>::iterator it = v.begin();
*it = 1;
assert(v[0] == 1);

Const 迭代器不會:

const std::vector<int> v{0};
std::vector<int>::const_iterator cit = v.begin();
// Compile time error: cannot modify container with const_iterator.
//*cit = 1;

如上所示, v.begin()const重載的,並根據容器變量的常量性返回iteratorconst_iterator

const_iterator彈出的常見情況是在const方法中使用this時:

class C {
    public:
        std::vector<int> v;
        void f() const {
            std::vector<int>::const_iterator it = this->v.begin();
        }
        void g(std::vector<int>::const_iterator& it) {}
};

const使this const成為常量,這使得this->v常量。

您通常可以使用auto忘記它,但是如果您開始傳遞這些迭代器,您將需要考慮它們的方法簽名。

與常量和非常量非常相似,您可以輕松地從非常量轉換為常量,但不能反過來:

std::vector<int> v{0};
std::vector<int>::iterator it = v.begin();

// non-const to const.
std::vector<int>::const_iterator cit = it;

// Compile time error: cannot modify container with const_iterator.
//*cit = 1;

// Compile time error: no conversion from const to no-const.
//it = ci1;

使用哪一個:類似於const intint :只要可以使用 const 迭代器(當您不需要用它們修改容器時),就更喜歡使用它們,以更好地記錄您的閱讀意圖而無需修改。

(正如其他人所說) const_iterator 不允許您修改它指向的元素,這在 const 類方法中很有用。 它還允許您表達您的意圖。

好的讓我先用非常簡單的例子來解釋它而不使用常量迭代器考慮我們有隨機整數集合“randomData”的集合

    for(vector<int>::iterator i = randomData.begin() ; i != randomData.end() ; ++i)*i = 0;
for(vector<int>::const_iterator i = randomData.begin() ; i!= randomData.end() ; ++i)cout << *i;

可以看出,在集合內部寫入/編輯數據時,使用了普通迭代器,但出於讀取目的,使用了常量迭代器。 如果您嘗試在第一個 for 循環中使用常量迭代器,則會出現錯誤。 作為一個經驗法則,使用常量迭代器來讀取 collection 中的數據。

暫無
暫無

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

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