關(guān)鍵字 const 非常多才多藝。在類的外部,你可以將它用于全局常量或命名空間常量,就像那些在文件、函數(shù)或模塊范圍內(nèi)被聲明為 static 的對象。在類的內(nèi)部,你可以將它用于 static 和 non-static 數(shù)據(jù)成員上。對于指針,你可以指定這個指針本身是 const,或者它所指向的數(shù)據(jù)是 const,或者兩者都是,或者都不是。
char greeting[] = "Hello";
char *p = greeting; // non-const pointer,
// non-const data
const char *p = greeting; // non-const pointer,
// const data
char * const p = greeting; // const pointer,
// non-const data
const char * const p = greeting; // const pointer,
// const data
這樣的語法本身其實并不像表面上那樣反復(fù)無常。如果 const 出現(xiàn)在 * 左邊,則指針指向的內(nèi)容為常量;如果 const 出現(xiàn)在 * 右邊,則指針自身為常量;如果 const 出現(xiàn)在 * 兩邊,則兩者都為常量。
當指針指向的內(nèi)容為常量時,一些人將 const 放在類型之前,另一些人將 const 放在類型之后 * 之前。兩者在意義上并沒有區(qū)別,所以,如下兩個函數(shù)具有相同的參數(shù)類型:
void f1(const Widget *pw); // f1 takes a pointer to a
// constant Widget object
void f2(Widget const *pw); // so does f2
因為它們都存在于實際的代碼中,你應(yīng)該習慣于這兩種形式。
STL iterators 以指針為原型,所以一個 iterator 在行為上非常類似于一個 T* 指針。聲明一個 iterator 為 const 就類似于聲明一個指針為 const(也就是說聲明一個 T* const 指針):不能將 iterator 指向另外一件不同的東西,但是它所指向的東西本身可以變化。如果你要一個 iterator 指向一個不能變化的東西(也就是 const T* 的 STL 對等物),你應(yīng)該用 const_iterator:
std::vector vec;
...
const std::vector::iterator iter = // iter acts like a T* const
vec.begin();
*iter = 10; // OK, changes what iter points to
++iter; // error! iter is const
std::vector::const_iterator cIter = //cIter acts like a const T*
vec.begin();
*cIter = 10; // error! *cIter is const
++cIter; // fine, changes cIter
char greeting[] = "Hello";
char *p = greeting; // non-const pointer,
// non-const data
const char *p = greeting; // non-const pointer,
// const data
char * const p = greeting; // const pointer,
// non-const data
const char * const p = greeting; // const pointer,
// const data
這樣的語法本身其實并不像表面上那樣反復(fù)無常。如果 const 出現(xiàn)在 * 左邊,則指針指向的內(nèi)容為常量;如果 const 出現(xiàn)在 * 右邊,則指針自身為常量;如果 const 出現(xiàn)在 * 兩邊,則兩者都為常量。
當指針指向的內(nèi)容為常量時,一些人將 const 放在類型之前,另一些人將 const 放在類型之后 * 之前。兩者在意義上并沒有區(qū)別,所以,如下兩個函數(shù)具有相同的參數(shù)類型:
void f1(const Widget *pw); // f1 takes a pointer to a
// constant Widget object
void f2(Widget const *pw); // so does f2
因為它們都存在于實際的代碼中,你應(yīng)該習慣于這兩種形式。
STL iterators 以指針為原型,所以一個 iterator 在行為上非常類似于一個 T* 指針。聲明一個 iterator 為 const 就類似于聲明一個指針為 const(也就是說聲明一個 T* const 指針):不能將 iterator 指向另外一件不同的東西,但是它所指向的東西本身可以變化。如果你要一個 iterator 指向一個不能變化的東西(也就是 const T* 的 STL 對等物),你應(yīng)該用 const_iterator:
std::vector vec;
...
const std::vector::iterator iter = // iter acts like a T* const
vec.begin();
*iter = 10; // OK, changes what iter points to
++iter; // error! iter is const
std::vector::const_iterator cIter = //cIter acts like a const T*
vec.begin();
*cIter = 10; // error! *cIter is const
++cIter; // fine, changes cIter