2014-09-11 58 views
18

來自Scott Mayers的「Effective STL」的項目26被標記爲「優選iteratorconst_iterator,reverse_iteratorconst reverse iterator」。常量迭代器在C++中仍然是邪惡的14

推理原因是insert()erase()的某些形式需要使用iterator,而從其他類型轉換是繁瑣且容易出錯的。此外,根據STL的實現,比較iteratorconst_iterator可能會有問題。

該書於2001年發佈。第26條中的建議是否仍然適用於當前的gcc狀態?

+2

當然'insert'和'erase'需要一個非const的'iterator':他們改變數據,所以'const'數據將是一個壞主意。 – gexicide 2014-09-11 09:12:49

+14

@gexicide:錯了。如果你可以調用'erase',無論如何你都可以訪問容器。出於這個原因,C++ 11改變了'erase'和'insert'函數來取'const_iterator's('iterator's總是可以轉換爲它們的'const_'變體)。 – Xeo 2014-09-11 09:14:05

+0

@Xeo:對,我的錯。感謝您清理它。 – gexicide 2014-09-11 09:15:06

回答

18

的C++ 14標準(N3936)保證iteratorconst_iterator可自由相當(§23.2.1[container.requirements.general]/P7):

在表達式

i == j 
i != j 
i < j 
i <= j 
i >= j 
i > j 
i - j 

其中容器的iterator類型的ij分別表示的對象, 任一個或兩個可通過所述容器的 const_iterator類型refe的目的來代替轉向相同的元素,但語義不變。

此外,容器的成員函數採取const_iterator參數的C++ 11(§C.2.13[diff.cpp03.containers] - 作爲可能會從標籤可以推斷,這是從C變更+ 03):

變化:簽名的變化:從iteratorconst_iterator參數

理由:Overspecification。 影響:下列成員函數的簽名從服用iterator改變爲服用 一個const_iterator

  • insert(iter, val)vectordequelistsetmultisetmapmultimap
  • insert(pos, beg, end)vectordeque, list, forward_list
  • erase(iter) for設置,多重集,地圖, multimap`
  • erase(begin, end) for設置,多重集,地圖, multimap`
  • 所有形式的list::splice
  • 所有形式的list::merge

容器要求已被類似地改變採用常量迭代器。此外,通過.base()成員函數可以很容易地從std::reverse_iterator獲取底層迭代器。因此,問題中提到的問題都不應該成爲合格編譯器的問題。

+3

您應該明確提到這是已經從C++ 03 - > C++ 11進行的更改。 – Xeo 2014-09-11 09:33:17

+0

關於具有.base的反向迭代器的說明也不錯。 – Puppy 2014-09-11 09:33:30

7

的建議已被顛倒,如可以從該標題爲即將到來的Effective Modern C++的項目13中可以看出:

不想const_iterators到迭代器

其原因是,C++ 11和C++ 14增加若干調整,使const_iterators很多更實用:

C++ 11增加

  • 所有標準庫容器的成員函數cbegin()cend()(及其反向對應項)
  • 使用迭代器標識位置的成員函數(例如, insert()erase())現在來const_iterator代替iterator

C++ 14完成,通過添加非成員cbegin()cend()(和它們的反轉對應物)