C 中const用法總結

2021-05-22 13:11:20 字數 4624 閱讀 9100

c++中用法總結

1.1.1. 定義普通常量

使用#define來定義常量也是常用方法,但const也可以用來定義常量,在[effective c++]中建議使用const代替#define來定義常量,因為const定義的常量具有型別資訊,而巨集沒有,所以使用const定義的常量在進行賦值操作時編譯器會進行更嚴格的型別檢查,是型別安全的。

const double pi = 3.1414926;

const int pool_size = 20;

定義常量有三種方法:巨集、const、enum,其中巨集應該盡量避免,而const與enum也各有優缺點,最大的區別就是enum只能用於定義整數,而不能定義浮點數;而對於定義邏輯關係較近的一組整數時比較適合使用enum,也可以考慮使用類代替enum(參見[??])。

常量必須在定義時進行初始化,之後便不能再賦值。說它不能被賦值並不是說常量的值是絕對不會改變的,只是說不能直接賦值,但可以通過指標及強制型別轉換、const_cast是可以改變常量的值的。

#include

using namespace std;

int main( void )

const int ci = 5;

const int* cpci = &ci;

int *pci = (int*)&ci;

cout<<"cpci = "<

return 0;

輸出結果:

cpci = 002dfac8, pci = 002dfac8

ci=5, *cpci=1, *pci=1

ci=5, *cpci=2, *pci=2

ci != *cpci

之所以使用ci直接輸出變數的值時顯示其值始終沒有改變,但通過指標間接顯示出來的值是改變了,而且輸出結果的最後一行很奇怪,ci的值與*cpci的值居然不相等,只因為編譯器在編譯時進行了優化,將**中的ci直接替換成了5,與巨集替換是相同的效果,而指標的值則是實際記憶體中的值。

所以,千萬不要試圖使用指標強行改變const變數的值,否則程式可能表現出錯誤的行為,而且查詢起來這種錯誤非常困難。在gcc 4.3.4和visual c++ 2010中均預設開啟了對常量的優化選項,目前還沒找到關閉該優化的命令列選項,一定不要自作聰明去改const變數的值。

1.1.2. 修飾指標

把const與指標放到一起,很多人便會想到乙個繞口令「指標常量與常量指標。「指標常量」即乙個指標變數,該變數不能被賦值,而指標指向的記憶體單元的內容是可以改變的;「常量指標」即乙個指向常量的指標,指標變數本身可以賦值,而指標指向的記憶體單元的內容是不可以被重新賦值的。

char a = 'a', b = 'b';

const char* ptoc = &a; // 常量指標

*ptoc = 'c'; // 改變指標指向記憶體單元的內容,不可以

ptoc = &b; // 改變指標的值,可以

char* const cp = &a; // 指標常量

cp = &b; // 改變指標的值,不可以

*cp = 'd'; // 改變指標指向記憶體單元的內容,可以

const char* const cptoc = &a; // 指向常量的指標常量

*cptoc = 'e'; // 不可以

cptoc = &b; // 不可以

const是修飾型別還是修飾指標,要看const的位置,放在*前就是修飾資料型別,放到*後就是修飾指標,const char和char const是一樣的。

建議:在不打算修改資料內容的時候都將指標定義成常量指標,不打算指標本身被修改的場合都定義成指標常量。盡可能地多用const,用錯了沒關係,編譯器會提示你的,只要能夠編譯通過,就不會因為用錯const而導致程式邏輯錯誤,應該說const負作用極小。

1.1.3. 修飾類成員常量

當使用const修飾類成員變數時便定義了常資料成員,它的使用與使用類外定義的常量本質上並沒有什麼區別,在這裡只想指出一點:有網友提到const資料成員只能被const修飾的函式使用這是沒有根據的,是錯誤的。

1.1.4. 修飾類成員函式

const修飾成員函式語法:

class socket

public:

typedef unsigned short socket_port_t;

socket_port_t localport( void )const

++readcount;

return _port;

private:

socket_port_t _port;

mutable int _readcount;

使用const修飾的成員函式不能修改類的成員變數,如成員_port,而且只能呼叫成員類物件const函式,但有個例外,就是mutable修飾的成員變數可以在const修飾的成員函式中被修改,如_readcount。

另外,const只能修飾非靜態函式。

建議:將所有不改變物件狀態的函式都使用const修飾符標識,以提高程式的可讀性。其實,標頭檔案就是最好的類介面的說明文件,越多的提供資訊就能使程式的可讀性越好,越利於維護。看到成員函式的const修飾符,讀者便立即明白該函式不會改變程式的狀態,這也有利於當程式狀態出現異常時的問題定位。

1.1.5. 修飾類物件、物件引用或物件指標(常量指標)

當const修飾自定義的類物件時,與修飾c++內建型別的變數的思想是一致的,但稍有不同,除了不能被賦值外,還不能呼叫沒有使用const修飾的非靜態成員函式。當const修飾類物件引用、指標時限制是一樣的,因為引用本身與直接使用該變數實質上沒有區別,而使用指標只是將.操作符改為了->本質上還是一樣的

const std::string hello = 「hello from noock tian;

std::cout<

hello = "hi"; // 不可以賦值

hello.push_back("!"); // 不可以

1.1.6. 修飾函式引數

const修飾函式的例子是很常見了,表示函式的引數在函式體內不會被意外修改,一般用於修飾輸入引數,例如標準庫中的字串連線函式。str1是輸出引數,其內容會被修改,而str2為輸入引數,其內容不會修改。

char* strcat(char* str1, const char* str2);

實際上在說到const用法一開始就提到,const只是一種宣告,但並不能保證,例如strcat函式雖然宣告了str2為const char*型,但並不能保證內部絕對不會修改str2的內容。但const從語言本身提供了一種編寫自描述性**的方法,只要使用函式與實現函式的雙方都達成一致的約定,按照契約程式設計,我們就可以認為const修飾的型別在函式體內不會被修改,這與const修飾類成員函式一樣,可以提高軟體的可讀性。

1.1.7. 修飾函式返回值

const可以用於修飾任何型別,只要返回值型別不是void,const就可以用來修飾返回值的型別。但實際上const用於修飾非引用的返回值型別是沒有意義的,因為返回值一般都會被賦值給另乙個變數,此時用於傳遞返回值的物件已經被銷毀,修飾返回值型別的const的作用也就終結了。

當返回值是引用型別時,如果該引用的值不希望被修改是可以宣告為常引用的,例如:

class socket

public:

const string& ip( void ) const

private:

string _ip;

socket sock;

string& ip = sock.ip(); // 不可以

const string& ip2 = sock.ip(); // 可以

string ip3 = sock.ip(); // socket::_ip被複製,可以

此處,為了減少構造臨時變數,將ip函式返回值定義為引用型別以提高程式執行效率,但為了保護內部狀態不會被客戶端**意外,返回值使用const修飾為常引用。但是,如果對於軟體安全性較高的場合,最好不要定義為引用,因為惡意的客戶端**是有可能修改socket::_ip的值的。

在c++中賦值運算子反預設返回值都是引用,但筆者認為定義為常引用更為合適,例如:

int main( void )

int a = 1,b = 2,c = 3,d = 4;

((a=b)=c)=d;

cout<<」a=」<

return 0;

輸出結果:

a=4, b=2, c=3, d=4

顯然,在實際工程中誰也不會寫出這樣的**,這段**卻是合法的,無疑這給程式設計師多了一種出錯的可能,如果把賦值運算子的返回值定義為常引用,則會減少程式設計師出錯的機會,例如[??]:

class object

public:

const object& operator=(const object& a)

int main( void )

object a, b, c, d;

a = b = c = d; // 可以

((a=b)=c)=d; // 不可以

return 0;

error: passing 『const object』 as 『this』 argument of 『const object& object::operator=(const object&)』 discards qualifiers.

當然,不同的編譯器可能錯誤提示不同。

C 中const用法總結

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

c 中const用法總結

const關鍵字在c 中的用法很普遍,總結了一下,大致有這些用法。1.阻止乙個變數被改變,使用const修飾,變數成為常量,因為以後不能修改它,所以定義時必須初始化。比如const int number 512。這和c語言中巨集有點類似,都是定義常量的,但是它們也有不同之處 巨集只是做簡單的字元替換...

c 中const用法總結

const關鍵字在c 中的用法很普遍,總結了一下,大致有這些用法。1.阻止乙個變數被改變,使用const修飾,變數成為常量,因為以後不能修改它,所以定義時必須初始化。比如const int number 512。這和c語言中巨集有點類似,都是定義常量的,但是它們也有不同之處 巨集只是做簡單的字元替換...