const關鍵字的使用

2022-05-03 11:21:22 字數 3919 閱讀 7132

看到const 關鍵字,c++程式設計師首先想到的可能是const常量。這可不是良好的條件反射。如果只知道用const 定義常量,那麼相當於把火藥僅用於製作鞭炮。

const 更大的魅力是它可以修飾函式的引數、返回值,甚至函式的定義體。

const 是constant 的縮寫,「恆定不變」的意思。被const 修飾的東西都受到強制保護,可以預防意外的變動,能提高程式的健壯性

所以很多c++程式設計書籍建議:「use const whenever you need」。

1、用const 修飾函式的引數

如果引數作輸出用,不論它是什麼資料型別,也不論它採用「指標傳遞」還是「引用傳遞」,都不能加const 修飾,否則該引數將失去輸出功能。const 只能修飾輸入引數

如果輸入引數採用「指標傳遞」,那麼加const 修飾可以防止意外地改動該指標,起到保護作用。

例如stringcopy 函式:

void stringcopy(char *strdestination, const char *strsource);

其中strsource 是輸入引數,strdestination 是輸出引數。給strsource 加上const修飾後,如果函式體內的語句試圖改動strsource 的內容,編譯器將指出錯誤。

如果輸入引數採用「值傳遞」,由於函式將自動產生臨時變數用於複製該引數,該輸入引數本來就無需保護,所以不要加const 修飾。

例如不要將函式void func1(int x) 寫成void func1(const int x)。同理不要將函式void func2(a a) 寫成void func2(const a a)。其中a 為使用者自定義的資料型別。

總結:const更多用於修飾指標/引用傳遞 的引數,起到保護引數的作用

對於非內部資料型別的引數而言,象void func(a a) 這樣宣告的函式注定效率比較底。因為函式體內將產生a 型別的臨時物件用於複製引數a,而臨時物件的構造、複製、析構過程都將消耗時間。

為了提高效率,可以將函式宣告改為void func(a &a),因為「引用傳遞」僅借用一下引數的別名而已,不需要產生臨時物件。但是函式void func(a &a) 存在乙個缺點:

「引用傳遞」有可能改變引數a,這是我們不期望的。解決這個問題很容易,加const修飾即可,因此函式最終成為void func(const a &a)。

以此類推,是否應將void func(int x) 改寫為void func(const int &x),以便提高效率?完全沒有必要,因為內部資料型別的引數不存在構造、析構的過程,而複製也非常快,

「值傳遞」和「引用傳遞」的效率幾乎相當。

問題是如此的纏綿,我只好將「const &」修飾輸入引數的用法總結一下。

對於非內部資料型別的輸入引數,應該將「值傳遞」的方式改為「const 引用傳遞」,目的是提高效率。例如將void func(a a) 改為void func(const a &a)。

對於內部資料型別的輸入引數,不要將「值傳遞」的方式改為「const 引用傳遞」。否則既達不到提高效率的目的,又降低了函式的可理解性。

例如void func(int x) 不應該改為void func(const int &x)。

2 、用const 修飾函式的返回值

如果給以「指標傳遞」方式的函式返回值加const 修飾,那麼函式返回值(即指標)的內容不能被修改,該返回值只能被賦給加const 修飾的同型別指標。

例如函式

const char * getstring(void);

如下語句將出現編譯錯誤:

char *str = getstring();

正確的用法是

const char *str = getstring();

如果函式返回值採用「值傳遞方式」,由於函式會把返回值複製到外部臨時的儲存單元中,加const 修飾沒有任何價值。

例如不要把函式int getint(void) 寫成const int getint(void)。

同理不要把函式a geta(void) 寫成const a geta(void),其中a 為使用者自定義的資料型別。

如果返回值不是內部資料型別,將函式a geta(void) 改寫為const a & geta(void)的確能提高效率。但此時千萬千萬要小心,一定要搞清楚函式究竟是想返回乙個物件的「拷貝」

還是僅返回「別名」就可以了,否則程式會出錯。

總結:const型別的返回值只能賦值給const型別的變數,否則會報錯

函式返回值採用「引用傳遞」的場合並不多,這種方式一般只出現在類的賦值函式中,目的是為了實現鏈式表達。

例如:

classa;

a a, b, c;

//a, b, c 為a 的物件

a = b = c; //

正常的鏈式賦值

(a = b) = c; //

不正常的鏈式賦值,但合法

如果將賦值函式的返回值加const 修飾,那麼該返回值的內容不允許被改動。上例中,語句 a = b = c 仍然正確,但是語句 (a = b) = c 則是非法的。

3、const 修飾成員函式

任何不會修改資料成員(即函式中的變數)的函式都應該宣告為const 型別。如果在編寫const 成員函式時,不慎修改了資料成員,或者呼叫了其它非const 成員函式,

編譯器將指出錯誤,這無疑會提高程式的健壯性。

以下程式中,類stack 的成員函式getcount 僅用於計數,從邏輯上講getcount 應當為const 函式。編譯器將指出getcount 函式中的錯誤。

class

stack

int pop(void

)

int getcount(void) const

//const 成員函式

private

:

intm_num;

int m_data[100

];};

const 成員函式的宣告看起來怪怪的:const 關鍵字只能放在函式宣告的尾部,大概是因為其它地方都已經被占用了。

1、const void*a:定義乙個void型別的指標,const修飾的是void指標指向的乙個常量,這個常量不能被修改

const

void *a;

*a=0x123;//

是編譯通不過的,因為*a中放的是個const值。const值是不能被改變的。

const

int m=1

;

const

int n=2

;a=&m; a=&n;//

編譯可以通過。

2、void* const a:定義乙個被const 修飾的void 型別的指標,指標本身的位址不能被修改,但是可以修改指標指向的物件

void* const

a;*a=0x123;//

沒問題a=(void*)&b;//

但是這樣不行的,因為a是const變數,可以改變a的指向,但是不能改變a本身

關於const函式的幾點規則:

1、 const物件只能訪問const成員函式,而非const物件可以訪問任意的成員函式,包括const成員函式

2、const物件的成員是不可修改的,然而const物件通過指標維護的物件卻是可以修改的

3、const成員函式不可以修改物件的資料,不管物件是否具有const性質.它在編譯時,以是否修改成員資料為依據,進行檢查

4、然而加上mutable修飾符的資料成員,對於任何情況下通過任何手段都可修改,自然此時的const成員函式是可以修改它的。

以上**自

關鍵字const的使用總結

1.const是一種型別修飾符,用於說明永不改變的物件,const物件一旦定義就無法再改變,所以const物件必須初始化。2.頂層const與底層const區別 位於 左側為底層const,位於 右側為頂層const 頂層const意味著記憶體本身儲存的資料是常量,如int const a 3 即變...

C 語言const關鍵字使用

1 const與變數 includeint main 2 cost與指標 1 const int p1 2 int const p2 3 int const p3 1 2 情況,指標所指向的資料是唯讀的,也就是p1,p2本身的值可以修改,但是他們指向的資料不能被修改 3 情況,指標是唯讀的,也就是p...

const關鍵字用法

1 const常量 如const int max 100 優點 const常量有資料型別,而巨集常量沒有資料型別。編譯器可以對前者進行型別安全檢查,而對後者只進行字元替換,沒有型別安全檢查,並且在字元替換時可能會產生意料不到的錯誤 邊際效應 2 const修飾類的資料成員 class a const...