《Effective C++ 》學習筆記——條款03

來源:互聯網
上載者:User

標籤:effective c++   學習筆記   條款03   

***************************************轉載請註明出處:http://blog.csdn.net/lttree********************************************


 一、 Accustoming Yourself to C++


Rule 03: Use const whenever possible.

條款03:儘可能的使用const


const就是常量,它允許你指定一個語義約束,編譯器會強制實施這項約束。

多才多藝的關鍵字const 有多種用途:

① 在classes 外部修飾global 或 namespace 範圍中的常量

② 修飾檔案、函數 或 區塊範圍(block scope )中被聲明為static的對象

③ 用它修飾classes內部的 static 和 non-static 成員變數


幾個重要的作用

1.對於指標

對於指標,可以設定 指標自身 、 指標所指物 或 兩者都是(或都不是) const

分辨方法也很簡單:如果const出現在星號(*)左面,表示被指標所指的物是常量,如果出現在右面,表示指標自身是常量。

自此,也可以擴充到 迭代器 ( iterator )

如果你想表示這個迭代器不得指向不同的東西,但它所指的東西的內容是可以改動的:

const std::vector<int>::iterator iter
反之,迭代器可以指向不同的東西,但所指的內容不可改動:

std::vector<int>::const_iterator iter

2.最具威力的用法——對於函式宣告時的應用

在一個函式宣告中,const 可以和 函數返回值、各參數、函數自身 產生關聯。

①函數的返回值

令函數返回一個常量值,往往可以降低因客戶錯誤而造成的意外,而又不至於放棄安全性和高效性。

②函數的參數

除非你有需要改動參數或local const對象,否則請將它們聲明為const。僅僅幾個字元,可以幫你省下很多的煩惱。

③函數自身(const成員函數)

const實施於成員函數的理由有兩個:

<1> 它們使classes介面比較容易理解(可以明確知道哪個函數可以改動對象內容,而哪個不能)

<2> 它們使“操作const對象”成為可能。 這個是 "pass by reference to 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;};

只要重載 operator[] 並對不同的版本給予不同的傳回型別,就可以令 const 和 non-const TextBlocks 獲得不同的處理:

std::cout<<tb[0];   // 沒問題,讀一個non-consttb[0] = ' x ';    // 沒問題,寫一個non-conststd::cout<<ctb[0];    // 沒問題,讀一個constctb[0] = ' x ';    // 錯誤,寫一個const

錯誤的原因是  企圖對一個“由const版之operator[]返回”的const char& 施行賦值動作。

此處要注意一下 non-const operator[] 的傳回型別是個 reference to char (引用char型),不是char,

否則 tb[0] = ‘ x ‘將無法通過編譯。


對於 成員函數如果是const意味性 有兩個流派:bitwise 和 logical

——bitwise const 陣營

奉行: 成員函數只有在不更改對象之任何成員變數(static除外)時才可以說是const。也就是說它不更改對象內的任何一個bit(位)。

優點:很容易偵測違反點,編譯器只需要尋找成員變數的賦值動作即可。

不足:不幸的是許多成員函數雖然不十足具備const性質卻能通過bitwise測試。

可以看下面這個例子:

const CTextBlock cctb("Hello");char* pc = &cctb[0];*pc = 'J';

這樣cctb現在儲存的是 "Jello"這個內容,顯然不符合const的定義


——logical const 陣營

奉行:一個const成員函數可以修改它所處理的對象內的某些bits,但只有在用戶端監測不出的情況下才如此。

例如 你的CTextBlock class 有可能快取(cache)文本區塊的長度以便詢問:

class CTextBlock{public:    ...    std::size_t length() const;private:    char* pText;    std::size_t textLength;<span style="white-space:pre"></span>// 最近一次計算的文本區塊長度。    bool lengthIsValid;<span style="white-space:pre"></span>// 目前長度是否有效};std::size_t CTextBlock::length() const{    if( !lengthIsValid)   {        textLength = std::strlen( pText );<span style="white-space:pre"></span>// 錯誤!在const 成員函數內不能賦值給這倆者        lengthIsValid = true;    }    return textLength;}

length實現肯定不是 bitwise const ,因為textLength 和 lengthIsValid都可能被修改。它們兩者被修改對const CTextBlock 對象而言雖然可以接受,但編譯器不同意。

所以就用一個mutable(可變的)來解決,用mutable來釋放掉non-static 成員變數的bitwise constness約束

class CTextBlock{public:    ...    std::size_t length() const;private:    char* pText;    mutable std::size_t textLength;// 這些成員變數即使在    mutable bool lengthIsValid;// const成員函數內也可更改};std::size_t CTextBlock::length() const{    if( !lengthIsValid)   {        textLength = std::strlen( pText );// 現在可以這樣        lengthIsValid = true;    }    return textLength;}

So 在const 和 non-const成員函數中避免重複

這個問題是由上面問題產生的,mutable固然可以解決變數的問題,但是如果這個東西很長,

我們則需要些兩份很長很長的怪物,so scary!

這就需要non-const來調用const的東西來避免重複,這樣改動也方便一些,

{

為什麼不讓const調用non-const的?

拜託,const成員函數承諾絕不改變其對象的邏輯狀態,non-const沒有

}


這樣就需要 調用 轉型 這個概念,看下面的例子:

class TextBlock{public:...const char& operator[](std::size_t position) const{.........return text[position];}char& operator[](std::size_t position){returnconst_cast<char&>(static_cast<const TextBlock&>(*this) [position]);}...};

這裡用到了兩個轉型:

static_cast     將non-const對象轉換成const對象

const_cast     移除const


結束語:

const是一個非常奇妙的且非比尋常的東西,

它可以用在 指標和迭代器上;

在指標、迭代器及reference指涉的對象身上;

在函數參數和傳回型別上;

在local變數身上; 

在成員函數身上,

等等。。。。


Please remember:

<1> 將某些東西聲明為 const 可協助編譯器偵測出錯誤用法。const可被施加於任何範圍內的對象、函數參數、函數傳回型別、成員函數本體。

<2> 編譯器強制實施bitwise constness,但你編寫程式時應該使用 conceptual constness(概念上的常量性)。

<3> 當const和non-const 成員函數有著實質等價的實現時,令non-const版本用const版本可避免代碼重複。



***************************************轉載請註明出處:http://blog.csdn.net/lttree********************************************

《Effective C++ 》學習筆記——條款03

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.