c++中const的各種用法

C++ const 允許指定一個語義約束,編譯器會強制實施這個約束,允許程序員告訴編譯器某值是保持不變的。如果在編程中確實有某個值保持不變,就應該明確使用const,這樣可以獲得編譯器的幫助。

1.const 修飾成員變量 

複製代碼
 1 #include<iostream>
 2 using namespace std;
 3 int main(){
 4     int a1=3;   ///non-const data
 5     const int a2=a1;    ///const data
 6 
 7     int * a3 = &a1;   ///non-const data,non-const pointer
 8     const int * a4 = &a1;   ///const data,non-const pointer
 9     int * const a5 = &a1;   ///non-const data,const pointer
10     int const * const a6 = &a1;   ///const data,const pointer
11     const int * const a7 = &a1;   ///const data,const pointer
12 
13     return 0;
14 }
複製代碼

const修飾指針變量時:

  (1)只有一個const,如果const位於*左側,表示指針所指數據是常量,不能通過解引用修改該數據;指針本身是變量,可以指向其他的內存單元。

  (2)只有一個const,如果const位於*右側,表示指針本身是常量,不能指向其他內存地址;指針所指的數據可以通過解引用修改。

  (3)兩個const,*左右各一個,表示指針和指針所指數據都不能修改。

2.const修飾函數參數

  傳遞過來的參數在函數內不可以改變,與上面修飾變量時的性質一樣。

void testModifyConst(const int _x) {
     _x=5;   ///編譯出錯
}


3.const修飾成員函數

(1)const修飾的成員函數不能修改任何的成員變量(mutable修飾的變量除外)

(2)const成員函數不能調用非onst成員函數,因爲非const成員函數可以會修改成員變量

複製代碼
 1 #include <iostream>
 2 using namespace std;
 3 class Point{
 4     public :
 5     Point(int _x):x(_x){}
 6 
 7     void testConstFunction(int _x) const{
 8 
 9         ///錯誤,在const成員函數中,不能修改任何類成員變量
10         x=_x;
11 
12         ///錯誤,const成員函數不能調用非onst成員函數,因爲非const成員函數可以會修改成員變量
13         modify_x(_x);
14     }
15 
16     void modify_x(int _x){
17         x=_x;
18     }
19 
20     int x;
21 };
複製代碼

 4.const修飾函數返回值

(1)指針傳遞

如果返回const data,non-const pointer,返回值也必須賦給const data,non-const pointer。因爲指針指向的數據是常量不能修改。

複製代碼
 1 const int * mallocA(){  ///const data,non-const pointer
 2     int *a=new int(2);
 3     return a;
 4 }
 5 
 6 int main()
 7 {
 8     const int *a = mallocA();
 9     ///int *b = mallocA();  ///編譯錯誤
10     return 0;
11 }
複製代碼

(2)值傳遞

 如果函數返回值採用“值傳遞方式”,由於函數會把返回值複製到外部臨時的存儲單元中,加const 修飾沒有任何價值。所以,對於值傳遞來說,加const沒有太多意義。

所以:

  不要把函數int GetInt(void) 寫成const int GetInt(void)。
  不要把函數A GetA(void) 寫成const A GetA(void),其中A 爲用戶自定義的數據類型。

一般情況下,函數的返回值爲某個對象時,如果將其聲明爲const時,多用於操作符的重載。通常,不建議用const修飾函數的返回值類型爲某個對象或對某個對象引用的情況。原因如下:如果返回值爲某個對象爲constconst A test = A 實例)或某個對象的引用爲constconst A& test = A實例) ,則返回值具有const屬性,則返回實例只能訪問類A中的公有(保護)數據成員和const成員函數,並且不允許對其進行賦值操作,這在一般情況下很少用到。

5.修飾類的成員函數提供重載

class A
{
           ......
  void f(int i)       {......} //
一個函數
  void f(int i) const {......} //
上一個函數的重載
           ......
}

      儘管函數名和參數列表都相同,void foo( ) const成員函數是可以與void foo( )並存的,可以形成重載! 我們假設調用語句爲obj.foo(),如果obj爲non-const對象,則調用foo()。如果obj爲const對象,則調用foo()const。另外要注意,假如沒有提供foo()const,則const obj調用foo()將會報錯。但假如是沒有提供foo(),則non-const obj調用foo()const是完全沒有問題的。也就是說,non-const對象可以調用const函數,但const對象不能調用non-const函數.

      const關鍵字所起作用的本質,就是把隱藏着的默認的this指針參數,改成const類型。也就是說:假如void foo( )函數被編譯器改寫爲 void foo(T* pThis),則void foo( ) const將會被改寫爲void foo(const T* pThis) 。i.e. 在函數末尾添加一個const,就相當於在隱藏的this參數類型前加一個const.這樣做有兩個效果,第一:編譯器將不允許foo()const修改pThis指向的對象的成員。第二、const對象只能調用const成員函數,否則就會報錯說把const T* 轉化爲T* 會丟失qualifier

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常量分配存儲空間,而是將它們保存在符號表中,這使得它成爲一個編譯期間的常量,沒有了存儲與讀內存的操作,使得它的效率也很高

8.將Const類型轉化爲非Const類型的方法

·             要大膽的使用const,這將給你帶來無盡的益處,但前提是你必須搞清楚原委;

·             要避免最一般的賦值操作錯誤,如將const變量賦值,具體可見思考題;

·             在參數中使用const應該使用引用或指針,而不是一般的對象實例,原因同上;

·             const在成員函數中的三種用法(參數、返回值、函數)要很好的使用;

·             不要輕易的將函數的返回值類型定爲const;

·             除了重載操作符外一般不要將返回值類型定爲對某個對象的const引用;

·             任何不會修改數據成員的函數都應該聲明爲const 類型。

9.額外補充

類內部的常量限制:使用這種類內部的初始化語法的時候,常量必須是被一個常量表達式

初始化的整型或枚舉類型,而且必須是static和const形式。

·             如何初始化類內部的常量:一種方法就是static 和 const 並用,在外部初始化,例如:

class A { public: A() {} private: static const int i; file://注意必須是靜態的! };

const int A::i=3;另一個很常見的方法就是初始化列表: class A { public: A(int

i=0):test(i) {} private: const int i; }; 還有一種方式就是在外部初始化,

·             如果在非const成員函數中,this指針只是一個類類型的;如果在const成員函數中,

this指針是一個const類類型的;如果在volatile成員函數中,this指針就是一個

volatile類類型的。

·           new返回的指針必須是const類型的。


詳細用法總結:http://blog.csdn.net/Eric_Jo/article/details/4138548



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章