天天看點

《Effective C++》讀書筆記之const高效使用

                                                                                                                        By Ryui Liu 2011/11/26

    C++中const關鍵字允許你指定一個語義限制即指定這是一個“不能被改動”的對象,而編譯器會強制實施這項限制。當你确實不希望某值保持不變時,你就該确實的說出來,這樣編譯器就可以幫助你確定這個值不被改變。

     const可以在class外部修飾global或namespace作用域中的常量,可以修飾檔案、函數、或區塊作用域中被static聲明的對象,可以修飾classes内部的static或non-static成員變量,也可以修飾常量指針、指針常量、指向常量的指針常量;const最有威力的用法還是在函數聲明時,可以和函數的傳回值,各個參數,函數自身産生關聯。

     const修飾變量時,如果const關鍵字出現在星号的左邊,表示被指物是常量(沒有星号時(即非指針變量)也适用),如果出現在星号的右邊,則表示指針自身是常量,如果在星号兩邊都出現,則被指物和指針兩者都是常量。

      const int i = 10;

      char greeting [] = "hello world";

      char greeting2[] = "qu world";

      const char *p  = greeting; 

      char const *q  = greeting;  // p和q都是常量指針

      char * const cq = greeeting; // cq為指針常量,不能改變它的指向

      *p = "aaaa";// error

       P = greeting2; //ok

       cq = greeting2; // error

       *cq ="aaaaa"; //ok 

      const char* const pq = greeting; //pq是指向常量的指針常量  

STL跌代器iterator 是普通指針,如果在其前面加上const修飾時,則該指針不能被改變,既疊代器不能改變,而const_iterator是一個指向常量的指針。例如:

      std::vector<int > vec;

      const std::vector<int>::iterator iter = vec.begin();

        *vec = 10 ;//ok  

        ++vec;  // error      

      std::vector<int>::const_iterator cIter = vec.begin();

         *vec = 10;//error

         ++vec;  //ok

     const修飾函數時,可以給參數加上const不希望修改參數的值,也可以給傳回值加上const不希望無意中改變傳回值。例如:

     class  aa{.....};

     const  aa operator*(const aa& a1,const aa& a2);

此處則不希望改變operator *的傳回值,假如一個混混沌沌的程式員寫出if(a*b = c), 編譯器給他錯誤提示了;如果沒有加上const,或許他會抓狂的。

     在c++面向對象程式設計中,常用const來修飾類的成員函數,這樣做是為了确認該成員函數可以作用于const對象身上。這樣做有兩個重要理由:第一、它們使class接口比較容易了解,得知哪個函數可以改動對象内容而哪個函數不可以,例如常見的get/set函數;第二、它們使“操作const對象”成為可能,這對編寫高效代碼是個關鍵。

需要提示的是:兩個成員函數如果隻有常量性不同即一個有const修飾,另一個沒有,可以被重載。

const char& operator[](std::size_t position)const {return ...}; //operator [] for const對象

char &operator[] (std::size_t position)(return ...);//operator[] for non-const 對象。

衆所周知,我們在const成員函數中不能修改成員變量,但當需要修改時就需要另外一個關鍵字---mutable.    

例如

class MutableTest

{

   public:

     MutableTest();

       ~MutableTest();

      void Output() const;

     int GetOutputTimes() const;

   private:

     mutable int m_iTimes;

 };

MutableTest::MutableTest()

{

 m_iTimes = 0;

}

MutableTest::~MutableTest()

{}

void MutableTest::Output() const

{

 cout << "Output for test!" << endl;

 m_iTimes++;

int MutableTest::GetOutputTimes() const

{

 return m_iTimes;

}

在這個例子中,将Output函數修飾為const,卻希望記錄輸出的次數,這時就需要改變m_iTimes的值,這個時候就需要mutable關鍵字來突破const關鍵字的限制了:m_iTimes在常成員函數中也可以被改變。

    總結:const可以被施加于任何作用域内的對象、函數參數、函數傳回類型、成員函數本體,将某些東西聲明為const可以幫助編譯器偵測錯誤用法。當需要在const的成員函數内部修改成員變量時,可以求助于mutable關鍵字。