C/C++ 中const關鍵字的用法小結
C++中的const關鍵字的用法非常靈活,而使用const將大大改善程式的健壯性。
Const作用
NO. | 作用 | 說明 | 參考 |
---|---|---|---|
1 | 可以定義const常量 | const int Max = 100; | |
2 | 便於進行型別檢查 | const常量有資料型別,而巨集常量沒有資料型別。編譯器可以對前者進行型別安全檢查,而對後者只進行字元替換,沒有型別安全檢查,並且在字元替換時可能會產生意料不到的錯誤 | void f(const int i) { ………} //對傳入的引數進行型別檢查,不匹配進行提示 |
3 | 可以保護被修飾的東西 | 防止意外的修改,增強程式的健壯性 | void f(const int i) { i=10; //error! } //如果在函式體內修改了i,編譯器就會報錯 |
4 | 可以很方便地進行引數的調整和修改 | 同巨集定義一樣,可以做到不變則已,一變都變 | |
5 | 為函式過載提供了一個參考 | class A { void f(int i) {……} //一個函式 void f(int i) const {……} //上一個函式的過載 …… }; | |
6 | 可以節省空間,避免不必要的記憶體分配 | const定義常量從彙編的角度來看,只是給出了對應的記憶體地址,而不是象#define一樣給出的是立即數,所以,const定義的常量在程式執行過程中只有一份拷貝,而#define定義的常量在記憶體中有若干個拷貝 | define PI 3.14159 //常量巨集 const doulbe Pi=3.14159; //此時並未將Pi放入ROM中 …… double i=Pi; //此時為Pi分配記憶體,以後不再分配! double I=PI; //編譯期間進行巨集替換,分配記憶體 double j=Pi; //沒有記憶體分配 double J=PI; //再進行巨集替換,又一次分配記憶體! |
7 | 提高了效率 | 編譯器通常不為普通const常量分配儲存空間,而是將它們儲存在符號表中,這使得它成為一個編譯期間的常量,沒有了儲存與讀記憶體的操作,使得它的效率也很高 |
提到 const 都知道是修飾常量的,在一個變數前加上const 關鍵字後這個常量就不可以再賦值了!
C語言中不是有#define嗎,幹嘛還要用const呢,我想事物的存在一定有它自己的道理,所以說const的存在一定有它的合理性,與預編譯指令相比,const修飾符有以下的優點:
1、預編譯指令只是對值進行簡單的替換,不能進行型別檢查
2、可以保護被修飾的東西,防止意外修改,增強程式的健壯性
3、編譯器通常不為普通const常量分配儲存空間,而是將它們儲存在符號表中,這使得它成為一個編譯期間的常量,沒有了儲存與讀記憶體的操作,使得它的效率也很高。
(以上三點摘抄自:https://www.jb51.net/article/70831.htm)
const 的應用
1 定義常量
const int a=5; int const a=5;
兩種用法是一樣的,這裡變數 a 在第一次定義時複製後,在程式執行中就不可再賦值改變了;
例如:
int main (int argc,char* argv) { const int a=5; int const b=5; a=3; //編譯時將會報錯,常量不可修改 b=8;//編譯時將會報錯,常量不可修改 }
const用於修飾常量靜態字串,
例如:
const char* Str="ABCDEFGH";
此時 const修飾過的str就是常量 我們不可更改Str的值 如 Str[3]='H'; 這時候是錯誤的,
2 常量指標與指標常量
很多人往往分不清這兩者的形態,
常量指標:
const int* pv;
int const* pv;
兩種定義方式一樣,都是定義一個常量指標;即不可通過這個指標修改所指向地址的值;但是所指向的地址的值是可以通過其他變數指標修改的;
但是常量指標可以賦值新的指向地址;
例如:
int main (int argc,char* argv) { int a=5; int b=7; const int* m=&a; int const* n=&b; int* p = n;//把常量指標 n 指向的地址賦給p; *m=3; //編譯時將會報錯,常量指標不可修改所指向的地址的值 *n=8;//編譯時將會報錯,常量指標不可修改所指向的地址的值 *p = 9; //編譯無措,可以通過變數指標修改常量指標所指向的地址的值 m=&b; //編譯無措,常量指標可以修改所指向的地址 n=&a; //編譯無措,常量指標可以修改所指向的地址 }
指標常量
int* const pv;
是指這個指標指向的地址不可在改變,但指向的地址的值可以再改變;(指標常量是指指標本身是個常量,不能在指向其他的地址)
int main(int argc,char* argv) { int a=5; int b=7; int* const m=&a; *m =8; //編譯無措 指標常量可以通過該指標修改所指向的地址的值 m = &b; //編譯出錯 指標常量不可修改所指向想的地址 }
指向常量的常指標
常量指標結合指標常量 即指向常量的常指標 表示指標本身和指標所指向的地址在定義時賦值後都不可再改變;
定義如下:
const int* const p;
那麼如何來區分常量指標和指標常量呢?
這就要明白關鍵字的結合優先順序了,
如:const int* p;
以*優先順序最高,先和int 結合 得到 " int* " (讀作整形指標) 然後(int*)和 const 結合得到 " const(int*)" (讀作常量指標) ,然後才和p結合得到"(const(int*))p" (讀作常量指標p),
int* const p;
同理,以*優先順序最高,先和int結合得到"int*"(讀作整形指標),然後(int*)和const結合得到"(int*)(const)"(讀作指標常量),最後才和p結合得到"(int*)(const)p"(讀作指標常量p)
3 常量函式
常見的定義方式
class AA { public: void mf_Fun1() { int b=10; num=b; } void mf_Fun2() const { cout<<num; //編譯無措,只讀取成員變數 num+=15; //錯誤 const 函式不可修改其成員變數,只可讀取 } } int main() { AA a1; const AA a2; //注意這裡的const關鍵字 a2.mf_Fun2(); a2.mf_Fun1(); // 錯誤,const的例項物件 不能訪問非const的函式 }
在類成員函式的宣告和定義中, const的函式不能對其資料成員進行修改操作。 const的物件,不能引用非const的成員函式。
這兒的const就是說這個函式操作不會對變數或是物件之類的值有影響 比如、有一個human類 ,現在要得到某個human類物件A的age 那麼肯定是不會因為想得到這個值而改變了age的大小,那麼就可以寫一個函式int getAge()const這樣就好 這麼做是為了防止在函式中對不應該在這裡改變的量不小心進行了改變 (抄錄自 https://zhidao.baidu.com/question/1702736835898870060.html)
4 在什麼情況下需要用到Const關鍵字?
4.1 修飾函式的引數
根據常量指標與指標常量,const修飾函式的引數也是分為三種情況
1、防止修改指標指向的內容
void StringCopy(char *strDestination,const char *strSource);
其中 strSource 是輸入引數,strDestination 是輸出引數。給 strSource 加上 const 修飾後,如果函式體內的語句試圖改動 strSource 的內容,編譯器將指出錯誤。
2、防止修改指標指向的地址
void swap ( int * const p1,int * const p2 )
指標p1和指標p2指向的地址都不能修改。
3、以上兩種的結合。
4.2 修飾函式的返回值
如果給以“指標傳遞”方式的函式返回值加 const 修飾,那麼函式返回值(即指標)的內容不能被修改,該返回值只能被賦給加const 修飾的同類型指標。 例如函式
const char * GetString(void);
如下語句將出現編譯錯誤:
char *str = GetString();
正確的用法是
const char *str = GetString();
4.3 修飾全域性變數
全域性變數的作用域是整個檔案,我們應該儘量避免使用全域性變數,因為一旦有一個函式改變了全域性變數的值,它也會影響到其他引用這個變數的函式,
導致除了bug後很難發現,如果一定要用全域性變數,我們應該儘量的使用const修飾符進行修飾,這樣防止不必要的人為修改,使用的方法與區域性變數是相同的。
4.4 暫存器變數定義和暫存器讀取
例如:
uint32_t* R0 =(uint32*)0x400F00FF; //定義一個地址為0x400F00FF的32bit暫存器變數
正確的定義方法:
uint32_t* const R0 =(uint32*)0x400F00FF;
//定義一個指標常量R0指向地址為0x400F00FF的暫存器 這樣就保證變數R0指向的地址的唯一性,
若是指向一個只讀暫存器則應該按如下定義:
const uint32_t* const R0 =(uint32*)0x400F00FF;
//定義一個指向常量的常指標 R0 指向地址為0x400F00FF的只讀暫存器,這樣就保證變數R0指向的地址的唯一性,同時不會因操作該指標修改指向地址的值
總結
到此這篇關於C/C++ 中const關鍵字的用法小結的文章就介紹到這了,更多相關C/C++ const關鍵字內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!