Item 3 盡量使用 const

2022-05-28 04:51:08 字數 4218 閱讀 5093

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...