char greeting = "hello";
char* p = greeting; //@ non-const data,non-const pointer
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
當指標指向的內容是常量時,將 const 放在型別前和放在型別後是沒有區別的:
//@ 等價的形式
void f1(const widget *pw);
void f1(widget const *pw);
當指標指向的內容是常量時,表示無法通過指標修改變數的值,但是可以通過其它方式修改指標指向變數的值:
int a = 1;
const int *p = &a;
cout << *p << endl; //@ 1
*p = 2; //@ error, data is const
a = 2;
cout << *p << endl; //@ 2
int a = 1, b = 2;
int* const p = &a;
cout << *p << endl; //@ 1
p = &b; //@ error, pointer is const
*p = b;
cout << *p << endl; //@ 2
stl 迭代器以指標為原型,所以乙個 iterator 在行為上非常類似於乙個 t* pointer。宣告乙個 iterator 為 const 就類似於宣告乙個 pointer 為 const(也就是說,宣告乙個 t* const pointer):
std::vectorvec;
const std::vector::iterator iter = vec.begin();
*iter = 10; //@ ok,change what the iterator point to
iter++; //@ error,iter is const
std::vector::const_iterator citer = vec.begin();
*citer = 10; //@ error,*citer is const
++citer; //@ ok,change citer
const 可以用在函式返回值,函式的個別引數,對於成員函式,還可以用於整個函式。
函式返回 const value 常常可以在不放棄安全和效率的前提下盡可能減少客戶造成的影響:
class rational;
const rational operator*(const rational& lhs,const rational& rhs);
上面函式返回 const object 的原因,可以避免客戶如下暴行:
rational a,b,c;
...(a * b) = c; //@ 為兩個數的乘積賦值,將返回值宣告為const 可以避免此問題
無論何時,只要你能,就應該將函式的引數宣告為 const 型別,除非你需要改變這個引數。
class textblock
//@ operator for non-const objects
char& operator(std::size_t position)
private:
std::string text;
};//@ 使用
textblock tb("hello");
std::cout << tb[0]; //@ calls non-const textblock::operator
const textblock ctb("world");
std::cout << ctb[0]; //@ calls const textblock::operator
const objects 在實際程式中最經常出現的是作為這樣乙個操作的結果:passed by pointer- or reference-to-const:
void print(const textblock& ctb) // in this function, ctb is const
//@ 對 const 和 non-const 的 textblocks 做不同的操作
std::cout << tb[0]; //@ fine — reading a non-const textblock
tb[0] = 'x'; //@ fine — writing a non-const textblock
std::cout << ctb[0]; //@ fine — reading a const textblock
ctb[0] = 'x'; //@ error! — writing a const textblock
這裡的錯誤只與被呼叫的 operator 的返回型別有關,而呼叫 operator 本身總是正確的。錯誤出現在企圖為 const char& 賦值的時候,因為它是 const 版本的 operator 的返回型別。
再請注意 non-const 版本的 operator 的返回型別是乙個 char 的引用而不是乙個 char 本身。如果 operator 只是返回乙個簡單的 char,下面的語句將無法編譯:
tb[0] = 'x';
位元常量(bitwise constness):如果乙個方法不改變物件的任何非靜態變數,那麼該方法是常量方法。 位元常量是c++定義常量的方式,然而乙個滿足位元常量的方法,卻不見得表現得像個常量,尤其資料成員是指標時:
class ctextblock // const) declaration of
// operator
private:
char *ptext;
};
看看 operator 的實現,它並沒有使用任何手段改變 ptext。結果,編譯器愉快地生成了 operator 的**,因為畢竟對所有編譯器而言,它都是 bitwise const 的,但是我們看看會發生什麼:
const ctextblock cctb("hello"); //@ declare constant object
char *pc = &cctb[0]; //@ call the const operator to get a pointer to cctb's data
*pc = 'j'; //@ cctb now has the value "jello"
這裡確實出了問題,你用乙個確定值建立乙個常量物件,然後你只是用它呼叫了 const 成員函式,但是你還是改變了它的值!
這一點不合理之處引發了邏輯常量(logical constness)的討論:常量方法可以修改資料成員, 只要客戶檢測不到變化就可以。可是常量方法修改資料成員c++編譯器不會同意的!這時我們需要 mutable 限定符:
class ctextblock ;
std::size_t ctextblock::length() const
return textlength;
}
通常我們需要定義成對的常量和普通方法,只是返回值的修改許可權不同。 當然我們不希望重新編寫方法的邏輯。最先想到的方法是常量方法呼叫普通方法,然而這是c++語法不允許的。 於是我們只能用普通方法呼叫常量方法,並做相應的型別轉換:
class textblock
char& operator(std::size_t position) // now just calls const op
...};
const 與迭代器:
const 與函式
Item3 盡可能使用const
const多才多藝,告訴編譯器和其他程式設計師某值應該保持不變。可以用在class外部修飾global或namespace作用域中的常量,修飾檔案,函式,或static物件。char greeting hello char p greeting non const pointer,non const...
條款3,盡量使用const
條款03 盡可能使用 const const允許你指定乙個語義約束,也就是指定乙個 不該被改動 的物件。const如果出現在星號左邊,表示被指物是常量,如果出現在星號右邊,表示指標自身是常量 如果出現在星號兩邊,表示被指物和指標都是常量。如果被指物是常量,有些程式會將關鍵字const寫在型別之前,有...
Effective C 盡量使用const
char greeting hello char p greeting const char p greeting char const p greeting const char const p greeting const在 號左邊,代表指標指向的物件是const的。如果在右邊,代表這個指標是c...