2010-07-25 128 views
2

Effective C++,第3項C++:使用常量與STL迭代器

/* case1 */ const std::vector<int>::iterator i // i acts like a T* const 
/* case2 */ std::vector<int>::const_iterator ci // ci acts like a const T* 

記住如何const適用,我曾經記得this article

基本上 '常量' 以下適用於任何 在它的左側(不包括 ,如果沒有任何其他 的情況,它適用於它的任何 直接右側)。

當我第一次讀到書中的第3項時,我預料它會在case1和case2中相反。

我應該將此案例視爲例外嗎?還是有一些更深層次的理解,我錯過了?

回答

1

引用的規則對於const關鍵字絕對正確。但是,在處理迭代器時,const_iterator類僅被命名爲(它可能同樣是readonly_iterator),因此關於const關鍵字的規則不適用。

但是,您可以申報情況1這樣的:

std::vector<int>::iterator const i 

就像你可以指定const int xint const x

迭代器指向的類型也在其容器的模板參數中指定,所以排序與聲明普通變量不同。

我看不出有什麼特別的經驗法則可以遵循 - 你的文章中的評論是正確的想法,你只需要學習如何將const_iterator作爲const T*等等。

5

你可以認爲它是作爲如果迭代器是typedef ED就像這樣:

typedef T* iterator; 
typedef const T* const_iterator; 

當您添加const要麼這些,它在頂層適用,即,對指針本身,而不是指向的對象,所以下面的等價符合:

const iterator it; // is the same as: 
T* const it; 

const const_iterator it; // is the same as: 
const T* const it; 

它們不是例外;這就是所有typedef的工作方式。

8

該規則按照廣告方式工作。

const std::vector<int>::iterator i 

右側的項目是iterator:迭代器是不可變的。你不能指定迭代器指向矢量中的不同項目,你不能增加它,它總是指向它初始化的項目。不過,您可以更改指向的項目。

這很少是所需的行爲,這就是爲什麼存在const_iterator typedef。

std::vector<int>::const_iterator ci 

迭代器可以四處移動,但指向的項不能修改。這幾乎總是你想要的 - 你想遍歷一個向量,但不能修改它的內容。

這裏沒有const關鍵字,所以你不能使用規則來弄清楚。對於這一個,你只需要瞭解什麼const_iterator被記錄下來。

+0

一個地方,我發現第一個案例是有用的保存搜索的輸出,從'std :: find_if'說。 'const std :: vector :: iterator i = std :: find_if(...);'說我想記住搜索的結果,並且我不想無意中改變結果。 – SCFrench 2010-07-25 18:18:56

1

我認爲const_iterator讓你感到困惑。這是一個簡單的typedefs的例子。

typedef int* Type; 
typedef const int* ConstType; 

int main() { 
    const Type a; // int * const 
    ConstType b; // const int * 
} 
0

const的情況下,1適用於迭代器,所以它使迭代器本身是常量。它對迭代器「指向」的項目沒有任何影響。 (這就好比在T* const,當指針const,而不是指向的T

在案例2中,在const只是名字const_iterator的一部分,所以它不能真正推斷出什麼const有。這個班可能只有一個不好的名字,可能根本就沒有任何固定的名字。但是,在這種情況下,const_iterator不允許修改其目標元素,因爲它的定義與標準庫中的類似。