Effective 3.儘可能的使用const

儘量一天一個條款的節奏吧。今天寫關於const的,const在c++中很平常,可是知道什麼時候應該運用,什麼時候用他來取代什麼,卻是一個沒想過的問題,這個條款中詳細的介紹了關於const的用法和好處。

首先來介紹下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

總結下: const 出現在星號左邊,表示被指物是常量,出現在星號右邊,表示指針自身是常量。(感覺這個自己看看就好,不用記啊!!!)
在const修飾的常量,只跟星號左右有關係,跟類型沒有關係。
對於 STL中 , C++也是有const指針的,也就是const_iterator. 但是跟上述的優點不一樣。
看下如下代碼。

std::vector<int> vec;
const std::vertor<int>::iterator iter = vec.begin(); 
*iter = 10// 沒問題 改變了iter的data.
++iter;         // 錯誤,iter是一個const.
std::vertor<int>::const_iterator Citer = vec.begin(); 
*cIter = 10;    //錯誤,*cIter是個const
++cIter;        //沒問題改變了cIter

所以看起來stl中的修飾,跟平常的不一樣,有點相反的樣子。

重點來了!!const 最有威力的地方,是在函數聲明的時候進行運用。
1. 讓函數返回一個常量值,可以降低別人調用的時候發生意外的情況。(請不要假設調用你寫的函數的人都能去看你的函數。或者知道這個函數的正確的用法, 有些時候,他的用法讓你完全想不到 !!!!)

class Rational(....);
const Rational operator*(const Rational& lhs, const Rational&rhs); //下面解釋爲什麼返回值用const修飾。
Rational a,b,c;
(a*b) = c;  //如果返回值不是const 是不是就成功了! 別問爲什麼有人會這麼用!!有可能!!
if(a*b = c) //判斷語句少打一個等號!是不是有可能發生!是不是可以減少好多錯誤的可能性!總比調試好

2 const 成員函數。
目的: 是爲了確認該成員函數可作用於const對象身上。
理由: 1 。 接口便於理解,哪個函數可以改動對象內容,哪個不行(const成員函數不會改動對象內容 理論上。。。)。2,它們使“操作const對象”成爲可能,這是提高效率的關鍵。以後會說。
有個有趣的事實(我也沒注意過): 兩個成員函數如果只是常量性不同,可以被重載。看下面的代碼

class TextBlock
{
public:
    const char& operator[](std::size_t position) const
    { return text[position]; }
    char& operator[](std::size_t position)
    { return text[position]; }
private:
    std::string text;
}

TextBlock tb("Hello");
std::cout << tb[0];         //調用 non-const Operator[]
tb[0] = 'x';                //成功,返回的不是const對象

TextBlock ctb("Hello");
std::cout << ctb[0];        //調用 const Operator[]
ctb[0] = 'x';               //錯誤,返回的是const對象

對於tb[0] = ‘x’ ,如果返回值是char 不是指針,那麼這個改動是不合法的,如果合法,改動的 也是他的副本,不是改動對象的本身,所以要注意這點。

如果const 函數返回一個指向成員內部的指針,就打破了對const的函數的理解的和運用(有點小疑問,回頭驗證下。)

class TextBlock
{
public:
    const char& operator[](std::size_t position) const
    { return text[position]; }
private:
    char* pText;
}

const CTextBlock cctb("Hello");
char * pc = &cctb[0];
*pc = 'J';      //修改了hello 違背了初衷。

“`

如果想在const函數中改變 成員變量, 可以用 mutable來聲明。

如果爲了避免代碼的重複, 也就是讓const的常量性消失, 可以領non-const函數調用const函數。中間可能需要一個轉型工作。(const_cast 消除const static_cast (增加const性) 後面條款會詳細說明轉型操作)

const 成員函數是不允許調用non-const成員函數的,違背了const 函數的初衷,不改變對象的內部數據在const函數中。儘量使用const可以提高代碼的效率和安全性。

請記住
將某些聲明聲明爲const 可以幫助編輯器偵測出錯誤用法。const可以被施加於任何域內對象,函數參數,函數返回值,成員函數本體。
對const函數,我們應該編寫概念上的常量性。
當const 和non-const 成員函數的代碼重複的時候,我們應該用non-const函數成員調用const函數,避免代碼重複。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章