看到const關鍵字,程式設計師首先想到的可能是const 常量。
const 更大的魅力是它可以修飾函式的引數、返回值,甚至函式的定義體。
const 是constant 的縮寫,「恆定不變」的意思。被const 修飾的東西都受到強制保護,可以預防意外的變動,能提高程式的健壯性。所以很多c++程式設計書籍建議:「use const whenever you need」。
如果引數作輸出用,不論它是什麼資料型別,也不論它採用下文討論的「指標傳遞」還是「引用傳遞」,都不能加const 修飾,否則該引數將失去輸出功能。const 只能修飾輸入引數,這又分為以下幾種情況。
1.1 const 用於修飾「指標傳遞」的引數,以防意外改動指標所指資料
例如某個 stringcopy 函式:
void stringcopy(char *strdestination, const char *strsource);
其中 strsource 是輸入引數,strdestination 是輸出引數。給 strsource 加上 const 修飾後,如果函式體內的語句試圖改動strsource 的內容,編譯器將指出錯誤。
當然也有方法繞過這個限制,例如可以在函式體內重新命名乙個指標 char * strsource2 = strsource ; 即可改動 strsource 所指的數值。
1.2 const 用於修飾「指標傳遞」的引數,以防意外改動指標本身
考慮如下**:
void swap ( int * const p1 , int * const p2 )
該定義將限制在函式 swap 內修改指標 p1 和 p2 的指向。
1.3 值傳遞的效率問題
如果輸入引數採用「值傳遞」,由於函式將自動產生臨時變數用於複製該引數,該輸入引數本來就無需保護,所以不要加const 修飾。
例如不要將函式 void func1 (int x) 寫成 void func1(const int x)。同理不要將函式 void func2(myclass a) 寫成void func2(const myclass a)。其中 myclass 為使用者自定義的資料型別。
然而,對於非內部資料型別的引數而言,類似 void func(myclass a) 這樣宣告的函式效率會比較底,這是因為函式體內將產生myclass型別的臨時物件用於複製引數a,而臨時物件的構造、複製、析構過程都將消耗時間。
為了提高效率,可以將函式宣告改為void func (myclass &a),因為「引用傳遞」僅借用一下引數的別名而已,不需要產生臨時物件。
但是函式void func(myclass & a) 存在乙個缺點:「引用傳遞」有可能改變引數a,這是我們不期望的。
解決這個問題很容易,加const修飾即可,因此函式最終成為void func(const myclass &a)。
以此類推,是否應將void func(int x) 改寫為void func(const int &x),以便提高效率?
答案是完全沒有必要,因為內部資料型別的引數不存在構造、析構的過程,而複製也非常快,「值傳遞」和「引用傳遞」的效率幾乎相當。所以對於內部資料型別的輸入引數,不要將「值傳遞」的方式改為「const 引用傳遞」。否則既達不到提高效率的目的,又降低了函式的可理解性。
2.1 const 修飾函式返回值(返回指標)
如果給以「指標傳遞」方式的函式返回值加 const 修飾,那麼函式返回值(即指標)的內容不能被修改,該返回值只能被賦給加const 修飾的同型別指標。
例如函式
const char * getstring(void);
如下語句將出現編譯錯誤:
char *str = getstring();
正確的用法是
const char *str = getstring();
2.2 const 用於修飾「返回引用」函式的返回值
如果函式返回值採用「值傳遞方式」,由於函式會把返回值複製到外部臨時的儲存單元中,加const 修飾沒有任何價值。例如把函式int getint(void) 寫成const int getint(void)是沒有意義的。
如果返回值不是內部資料型別,將函式myclass getobj(void) 改寫為const myclass & getobj(void)的確能提高效率。但此時千萬千萬要小心,一定要搞清楚函式究竟是想返回乙個物件的「拷貝」還是僅返回「別名」就可以了,否則程式會出錯。
這裡對函式返回值使用 const 的目的在於限制不能將函式呼叫表示式作為左值使用。例如有如下函式:
int & min ( int &i, int &j);
可以對函式呼叫進行賦值,因為它返回的是左值: min ( a , b )=4;
但是,如果對函式的返回值限定為 const 的,即丁奕:const int & min ( int & i, int &j );
那麼,就不能對 min ( a, b ) 呼叫進行賦值了。
事實上,函式返回值採用「引用傳遞」的場合並不多,這種方式一般只出現在類的賦值函式中,目的是為了實現鏈式表達。
例如:class
a
;
a a, b, c;
// a, b, c 為a 的物件
a = b = c;
// 正常的鏈式賦值
(a = b) = c;
// 不正常的鏈式賦值,但合法
如果將賦值函式的返回值加const 修飾,那麼該返回值的內容不允許被改動。上例中,語句 a = b = c 仍然正確,但是語句 (a = b) = c 則是非法的。
const修飾函式引數時的過載
const修飾成員函式時的過載 根本原則是表示的引數是變數還是常量。void fun const int i void fun int i int main 結果 編譯錯誤,提示重定義 其實很好理解 void fun int a 和 void fun const int a 實際上沒有區別,因為函式...
(3)用const修飾函式的引數和函式的返回值
3 用const修飾函式的引數和函式的返回值 在定義函式時常用到const,主要是用來修飾引數和返回值。這樣做的目的是讓編譯器為程式設計師做變數唯讀性的檢查,以使程式更加健壯。下面是乙個例子。1.include 2.3.void disp1 const int ri 4.7.void disp2 c...
Const修飾函式
用const修飾函式的返回值 如果給以 指標傳遞 方式的函式返回值加const修飾,那麼函式返回值 即指標 的內容不能被修改,該返回值只能被賦給加const修飾的同型別指標。例如函式const char getstring void 如下語句將出現編譯錯誤 char str getstring 正確...