天天看點

【03】盡可能使用const

1、為什麼搞出const關鍵字?

  const指定一個語義限制,指定一個對象不可修改。如果一個對象不可修改,就應該說出來。

2、const與指針

  const可以修飾指向之物,也可以修改指針本身。STL中的疊代器是對指針的封裝,是以,疊代器也有兩個概念:指向常量對象的疊代器和常量疊代器。

  vector<int>::const_iterator; //指向常量的疊代器

  const vector<int>::iterator; // 常量疊代器

3、const可以與方法産生關聯,可以用在方法前,方法中(形參表中),方法後。首先考慮,用在方法前,表示傳回值是常量。為什麼要傳回const對象呢?

  我們知道,方法傳回值是一個臨時對象,隻有類型,沒有名稱,這個臨時對象是方法内局部對象的副本。如果傳回不是一個常量,用戶端就能實作下面的暴行:

  Rational a,b,c; 

  (a*b)=c; //對方法傳回值進行指派。

  對于内置類型,這樣的指派行為是錯誤的。對于自定義類型,也應該報錯。有一個準則要遵守:自定義類型應該和内置類型在行為上保持一緻,除非有特殊情況。是以,為了避免用戶端對方法傳回值進行指派,請傳回一個const對象。

4、const在方法中,也就是出現在形參表中,這種情況很好了解,表示形參不可修改。需要注意的是:形參表不同,可以構成過載。如果形參表相同,隻是常量性不同,能否構成過載?能不能構成過載的關鍵是:編譯器能不能根據實參确定調用哪個方法,也就是過載方法的比對程度不一樣。

  如果形參是引用或者指針,可以構成過載,這種情況下,形參是實參的别名,根據實參的常量性,可以确定調用哪個方法。

  如果形參不是引用或者指針,不能構成過載,這種情況下,形參是實參的副本,與實參沒有了關系,他們和實參的比對程度是一樣的。

5、const在方法後,表示常量方法,應該盡量使用常量方法。有兩個好處:a、接口容易了解,明确表示不會修改對象内容;b、使得const對象可以調用。

  考慮,我們知道non-const對象可以調用const成員方法,但是,const對象不能調用non-const成員方法,因為non-const成員方法可能會修改對象。為了讓const對象調用non-const成員方法,有兩種辦法:一是使用const_cast<T&>或者const_cast<T*>去除對象的常量性,二是如果不修改對象,使用const成員方法,顯然第二種辦法更好。

6、根據成員方法的常量性,可以過載。為什麼?我們知道成員方法有個隐式的常量this指針(不能指向其他對象),const成員方法限制了this指針指向const。是以,編譯器可以根據方法擁有者的常量性,決定哪個方法更比對。

7、如果傳回對象的内部資料,const成員方法應該傳回const引用,防止外部修改,non-const成員方法應該傳回non-const引用。這裡特别注意一點,内置類型的臨時對象是不可修改的(exception的臨時對象是可以修改的),也就是說,内置類型的臨時對象不能指派給non-const引用,考慮一下為什麼?

  方法傳回對象的内部資料,傳回值不是引用,而是内部資料的副本。第一個理由上面講了,防止用戶端對傳回值指派,第二個理由是,如果傳回值不是const,就可以指派給non-const引用,程式員用這個引用期望修改對象内部資料,是辦不到的,這個時候修改的是臨時對象,這往往不是程式員所期望的。

8、傳回對象的内部資料,const成員方法為什麼傳回const引用?

  我們知道,const成員方法的語義是說,不修改對象。但是由于暴露了内部資料,自己承諾不修改,但是由于自己的原因,暴露了内部資料,導緻外部可以間接修改對象(我不殺伯仁,奈何伯仁因我而死)。為了避免這種情況,傳回const引用,限制外部也不能修改。

9、在有些極端情況下,const成員方法也要修改對象的一部分内部資料,但是我又不想把它設計成non-const成員方法,因為non-const成員方法可以修改對象内的任意資料。這種情況下,可以使用mutable修飾字段,明确表示這些字段可以在const成員方法中修改。