1.const關(guān)鍵字的性質(zhì)

簡(jiǎn)單來(lái)說(shuō):const關(guān)鍵字修飾的變量具有常屬性。 即它所修飾的變量不能被修改。

2.修飾局部變量

1 const int a = 10;2 int const b = 20;

這兩種寫法是等價(jià)的,都是表示變量的值不能被改變,需要注意的是,用const修飾變量時(shí),一定要給變量初始化,否則之后就不能再進(jìn)行賦值了,而且編譯器也不允許不賦初值的寫法:

在C++中不賦初值的表達(dá)一寫出來(lái),編譯器即報(bào)錯(cuò),且編譯不通過(guò)。

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

在C中不賦初值的表達(dá)寫出來(lái)時(shí)不報(bào)錯(cuò),編譯時(shí)只有警告,編譯可以通過(guò)。而當(dāng)你真正給它賦值時(shí)才會(huì)報(bào)錯(cuò),那么沒(méi)有初值也不能被賦值這樣的變量有什么用哪?

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

1 const chsr* p = "qwerty"; //const用于修飾常量靜態(tài)字符串

如果沒(méi)有const的修飾,我們可能會(huì)在后面有意無(wú)意的寫p[4]=’x’這樣的語(yǔ)句,這樣會(huì)導(dǎo)致對(duì)只讀內(nèi)存區(qū)域的賦值,然后程序會(huì)立刻異常終止。有了const,這個(gè)錯(cuò)誤就能在程序被編譯的時(shí)候就立即檢查出來(lái),這就是const的好處。讓邏輯錯(cuò)誤在編譯期被發(fā)現(xiàn)。(這個(gè)特性在C/C++中相同)

3.修飾指針

常量指針是指針?biāo)赶虻膬?nèi)容是常量,不可被修改。

1 const int * n =?。Γ?2 int const * n?。健。Γ?

上面兩種寫法也是等價(jià)的,性質(zhì)如下:

1)常量指針通過(guò)不能這個(gè)指針改變變量的值,但是可以通過(guò)其他的引用來(lái)改變變量的值的。

1 const int *n = &a;2     *n = b;

上面的寫法報(bào)錯(cuò)seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

1 int c = 3;2 const int *n = &a;3 a = 10;4 a = c;

這樣賦值是可以的。

2)常量指針指向的值不能改變,但是指針本身可以改變,即常量指針可以指向其他的地址。

1   int a = 1;2    int b = 2;3     const int *n = &a;4     n = &b;

指針常量是指指針本身是個(gè)常量,不能在指向其他的地址,寫法如下:

      a =       b =       *  n = &     *n = b;
5      b = a;

而這么寫是錯(cuò)誤的

1 int a = 1;2 int b = 2;3 int c = 3;4 int * const n = &a;5 n = &b;

它們的區(qū)別在于const的位置,可以這樣記憶:const在“*”前面時(shí)它修飾(*n),而*n是n所指向的變量,所以是常量指針,const在“*”后面時(shí)它修飾(n),使指針變?yōu)槌A?,所以是指針常量?/p>

指向常量的常指針

1 const int * const p= &a;2 int const * const p= &a;

指針指向的位置不能改變并且也不能通過(guò)這個(gè)指針改變變量的值,但是依然可以通過(guò)變量賦值,或其他的普通指針改變變量的值。

(這種用法在C和C++中是相同的。)

4.修飾引用

1 int a = 1;2 int const &a = b;3 const int &a = b;

兩種定義形式在本質(zhì)上是一樣的

5.函數(shù)中使用const

(1)修飾函數(shù)參數(shù)

根據(jù)const修飾指針的特性,const修飾函數(shù)的參數(shù)也是分為三種情況

1 void StrCopy(char *strdes, const char *strsrc);//防止修改指針指向的內(nèi)容

其中 strsrc是輸入?yún)?shù),strdes是輸出參數(shù)。給 strsrc 加上 const 修飾后,如果函數(shù)體內(nèi)的語(yǔ)句試圖改動(dòng) sresrc 的內(nèi)容,編譯器將指出錯(cuò)誤。

1 void swap ( int * const p1 , int * const p2 )  //防止修改指針指向的地址

 

指針p1和指針p2指向的地址都不能修改。

1 void test ( const int * const p1 , const int * const p2 )  //以上兩種的結(jié)合

另外當(dāng)參數(shù)為引用時(shí)

1 void function(const Class& Var); //引用參數(shù)在函數(shù)內(nèi)不可以改變 2 void function(const TYPE& Var); //引用參數(shù)在函數(shù)內(nèi)為常量不可變

(這樣的一個(gè)const引用傳遞和最普通的函數(shù)按值傳遞的效果是一模一樣的,他禁止對(duì)引用的對(duì)象的一切修改,唯一不同的是按值傳遞會(huì)先建立一個(gè)類對(duì)象的副本, 然后傳遞過(guò)去,而它直接傳遞地址,所以這種傳遞比按值傳遞更有效.另外只有引用的const傳遞可以傳遞一個(gè)臨時(shí)對(duì)象,因?yàn)榕R時(shí)對(duì)象都是const屬性, 且是不可見(jiàn)的,他短時(shí)間存在一個(gè)局部域中,所以不能使用指針,只有引用的const傳遞能夠捕捉到這個(gè)家伙。)

(2)修飾函數(shù)返回值

如果給以“指針傳遞”方式的函數(shù)返回值加 const 修飾,那么函數(shù)返回值(即指針)的內(nèi)容不能被修改,該返回值只能被賦給加const 修飾的同類型指針。

1 const int * fun2()    //調(diào)用時(shí) const int *pValue = fun2();  
2                             //我們可以把fun2()看作成一個(gè)變量,即指針內(nèi)容不可變。 3 c.int* const fun3()   //調(diào)用時(shí) int * const pValue = fun2();  
4                             //我們可以把fun2()看作成一個(gè)變量,即指針本身不可變。

const int fun1()   //這個(gè)其實(shí)無(wú)意義,因?yàn)閰?shù)返回本身就是賦值。

6.修飾類相關(guān)

(1)用const修飾的類成員變量,只能在類的構(gòu)造函數(shù)初始化列表中賦值,不能在類構(gòu)造函數(shù)體內(nèi)賦值。

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

 1 class A 2 { 3 public: 4     A(int x) : a(x)  // 正確 5     { 6          //a = x;    // 錯(cuò)誤 7     } 8 private: 9     const int a;10 };

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

(2)const修飾成員函數(shù)

用const修飾的類成員函數(shù),在該函數(shù)體內(nèi)不能改變?cè)擃悓?duì)象的任何成員變量, 也不能調(diào)用類中任何非const成員函數(shù)。一般寫在函數(shù)的最后來(lái)修飾。

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

 1 class A 2 { 3 public: 4     int& getValue() const 5     { 6         // a = 10;    // 錯(cuò)誤 7         return a; 8     } 9 private:10     int a;            // 非const成員變量11 };

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

a. const成員函數(shù)不被允許修改它所在對(duì)象的任何一個(gè)數(shù)據(jù)成員。

b. const成員函數(shù)能夠訪問(wèn)對(duì)象的const成員,而其他成員函數(shù)不可以。

(3)const修飾類對(duì)象/對(duì)象指針/對(duì)象引用

用const修飾的類對(duì)象表示該對(duì)象為常量對(duì)象,該對(duì)象內(nèi)的任何成員變量都不能被修改。對(duì)于對(duì)象指針和對(duì)象引用也是一樣。
因此不能調(diào)用該對(duì)象的任何非const成員函數(shù),因?yàn)閷?duì)非const成員函數(shù)的調(diào)用會(huì)有修改成員變量的企圖。

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

 1 class A 2 { 3  public: 4     void funcA() {} 5     void funcB() const {} 6 }; 7 int main 8 { 9     const A a;10     a.funcB();    // 正確11     a.funcA();    // X12 13     const A* b = new A();14     b->funcB();    // 正確15     b->funcA();    // X16 }

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

(4)在類內(nèi)重載成員函數(shù)

1 class A2 {3 public:4     void func() {}5     void func() const {}   // 重載6 };

另外,const數(shù)據(jù)成員只在某個(gè)對(duì)象生存期內(nèi)是常量,而對(duì)整個(gè)類而言是可變的,因?yàn)轭惪梢詣?chuàng)建多個(gè)對(duì)象,不同對(duì)象的const數(shù)據(jù)成員值可以不同。

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

class A
{public:
    A(int size) 
         : _size(size)  // 正確    {}private:    const int _size;
};
A a(10);  //對(duì)象a的_size值為10A b(20);  //對(duì)象b的_size值為20

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

那么,怎樣才能建立在整個(gè)類中都恒定的常量呢?用枚舉常量。

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

class A
{public:   enum{SIZE1 = 10, SIZE2 = 20};//枚舉常量private:     int arr1[SIZE1];     int arr2[SIZE2];
};

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

枚舉常量不會(huì)占用對(duì)象的存儲(chǔ)空間,它們?cè)诰幾g時(shí)被全部求值。但缺點(diǎn)是隱含數(shù)據(jù)類型是只能整數(shù),最大值有限,且不能表示浮點(diǎn)數(shù)。

7.修飾全局變量

全局變量的作用域是整個(gè)文件,我們應(yīng)該盡量避免使用全局變量,以為一旦有一個(gè)函數(shù)改變了全局變量的值,它也會(huì)影響到其他引用這個(gè)變量的函數(shù),導(dǎo)致除了bug后很難發(fā)現(xiàn),如果一定要用全局變量,我們應(yīng)該盡量的使用const修飾符進(jìn)行修飾,這樣方式不必要的以為修改,使用的方法與局部變量是相同的。

8.const常量與宏常量的區(qū)別

(1).便于進(jìn)行類型檢查

const常量有數(shù)據(jù)類型,而宏常量沒(méi)有數(shù)據(jù)類型。編譯器可以對(duì)前者進(jìn)行類型安全檢查,而對(duì)后者只進(jìn)行字符替換,沒(méi)有類型安全檢查,并且在字符替換時(shí)可能會(huì)產(chǎn)生意料不到的錯(cuò)誤(邊際效應(yīng))。

1 //例子:2 void f(const int i) { .........}   //對(duì)傳入的參數(shù)進(jìn)行類型檢查,不匹配進(jìn)行提示

(2)可以節(jié)省空間,避免不必要的內(nèi)存分配

const定義常量從匯編的角度來(lái)看,只是給出了對(duì)應(yīng)的內(nèi)存地址,而不是象#define一樣給出的是立即數(shù),所以,const定義的常量在程序運(yùn)行過(guò)程中只有一份拷貝,而#define定義的常量在內(nèi)存中有若干個(gè)拷貝。

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

1 #define PI 3.14159         //常量宏2 const doulbe  Pi=3.14159;  //此時(shí)并未將Pi放入ROM中3               ......4 double i=Pi;   //此時(shí)為Pi分配內(nèi)存,以后不再分配!5 double I=PI;  //編譯期間進(jìn)行宏替換,分配內(nèi)存6 double j=Pi;  //沒(méi)有內(nèi)存分配7 double J=PI;  //再進(jìn)行宏替換,又一次分配內(nèi)存!

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

(3)提高了效率 

 宏定義是一個(gè)“編譯時(shí)”概念,在預(yù)處理階段展開(kāi),不能對(duì)宏定義進(jìn)行調(diào)試,生命周期結(jié)束于編譯時(shí)期。const常量是一個(gè)“運(yùn)行時(shí)”概念,在程序運(yùn)行時(shí)使用,類似于一個(gè)只讀數(shù)據(jù)。

編譯器通常不為普通const常量分配存儲(chǔ)空間,而是將它們保存在符號(hào)表中,這使得它成為一個(gè)編譯期間的常量,沒(méi)有了存儲(chǔ)與讀內(nèi)存的操作,使得它的效率也很高

(4)可以保護(hù)被它修飾的東西

防止意外的修改,增強(qiáng)程序的健壯性。

1 void f(const int i) { i=10;//error! } //如果在函數(shù)體內(nèi)修改了i,編譯器就會(huì)報(bào)錯(cuò)2

(5)為函數(shù)重載提供了一個(gè)參考

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

1 class A2 {3            ......4   void f(int i)       {......} //一個(gè)函數(shù)5   void f(int i) const {......} //上一個(gè)函數(shù)的重載6            ......7 };

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

(6)定義域不同

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

 1 void f1 () 2 { 3     #define N 12 4     const int n 12; 5 } 6 void f2 () 7 { 8     cout<<N <<endl; //正確,N已經(jīng)定義過(guò),不受定義域限制 9     cout<<n <<endl; //錯(cuò)誤,n定義域只在f1函數(shù)中。若想在f2中使用需定義為全局的10 }

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

(7)做函數(shù)參數(shù)

   宏定義不能作為參數(shù)傳遞給函數(shù);const常量可以在函數(shù)的參數(shù)列表中出現(xiàn)。

9.const_cast

const_cast運(yùn)算符用來(lái)修改類型的const或volatile屬性。
(1)常量指針被轉(zhuǎn)化成非常量的指針,并且仍然指向原來(lái)的對(duì)象;
(2)常量引用被轉(zhuǎn)換成非常量的引用,并且仍然指向原來(lái)的對(duì)象。

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

1 void func()2 {3     const int a = 10;4     int* p = const_cast<int*> (&a);5     *p = 20;6     std::cout<<*p;    // 207     std::cout<<a;     // 108 }

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

注:C++中使用const 常量而不使用宏常量,即const 常量完全取代宏常量。

ps:高質(zhì)量C/C++第5章、第11章。

http://www.cnblogs.com/33debug/p/7199857.html