C/C++ const 詳解

一. const 的作用

(1) 可以定義 const 常量 

const int Max=100;

int Array[Max];

(2) 可以保護被修飾的東西,防止意外的修改,增強程序的健壯性

如果在函數體內修改了i,編譯器就會報錯;

void f (const int i) 
{ 
    i=10;//error! 
}

(3) 爲函數重載提供了一個參考

class
  1. ...... 
  2. void f(int i)       {......}//一個函數 
  3. void f(int i)const {......}//上一個函數的重載 
  4. ...... 
  5. }; 

 

(4) 可以節省空間,避免不必要的內存分配

#define PI 3.14159         //常量宏 
  1. const doulbe  Pi=3.14159;  //此時並未將Pi放入ROM中 
  2. ...... 
  3. double i=Pi;               //此時爲Pi分配內存,以後不再分配! 
  4. double I=PI;              //編譯期間進行宏替換,分配內存 
  5. double j=Pi;               //沒有內存分配 
  6. double J=PI;              //再進行宏替換,又一次分配內存! 

const定義常量從彙編的角度來看,只是給出了對應的內存地址,而不是象#define一樣給出的是立即數,所以,const定義的常量在程序運行過程中只有一份拷貝,而#define定義的常量在內存中有若干個拷貝

 

(5) 提高了效率
編譯器通常不爲普通const常量分配存儲空間,而是將它們保存在符號表中,這使得它成爲一個編譯期間的常量,沒有了存儲與讀內存的操作,使得它的效率也很高。

 

二. 使用 const


(1) 修飾一般常量,常數組,常對象
修飾符const可以用在類型說明符前,也可以用在類型說明符後。 例如:

//常量 
  1. int const x=2; 
  2. const int x=2; 
  3.  
  4. //常數組 
  5. int const a[5]={1, 2, 3, 4, 5}; 
  6. const int a[5]={1, 2, 3, 4, 5}; 
  7.  
  8. //常對象 
  9. class A; 
  10. const A a; 
  11. A const a; 

(2) 修飾指針

const int *A;    
  1. int const *A;//const修飾指向的對象,A可變,A指向的對象不可變 
  2. int *const A;//const修飾指針A,     A不可變,A指向的對象可變 
  3. const int *const A;//指針A和A指向的對象都不可變 

<<effective C++>>上有個好記的方法:const在*號左邊修飾的是指針所指的內容;const在*號右邊修飾的是指針
簡單記就是:左內容,右指針。

也可以這樣理解:先忽略類型名,然後看const離哪個近,就修飾誰

如:const [int] *p; //先去掉int,這時const 修飾*p,p是指針,*p是指針指向的對象,不可變

(3) 修飾引用

const double & v; //該引用所引用的對象不能被更新

(4) 修飾函數的返回值

const修飾符也可以修飾函數的返回值,返回值不可被改變,格式如下:

 
const int Fun1();

const MyClass Fun2();

(5) 修飾類的成員函數
const修飾符也可以修飾類的成員函數,格式如下:

class ClassName  
  1. public
  2. int Fun() const
  3. ..... 
  4. }; 
這樣,在調用函數Fun時就不能修改類裏面的數據

 class

  1. public
  2. A(int i=0):test(i) {} //初始化列表 
  3. private
  4. const int test;
  5. }

(6) 在另一連接文件中引用const常量

extern constint i;    //正確的引用 
  1. externconstint j=10; //錯誤!常量不可以被再次賦值 
三. 幾個要說明的問題
(1) 如何初始化類內部的常量?
方法1:初始化列表
class A
{
public:
	A(int num):i(num) //用num來初始化i
	{};

private:
	const int i;
};

方法2: 外部初始化

 

(2) 放在類內部的常量有什麼限制?

//error
class A
{
public:
  A()
  {};

private:
  const int c1 = 7;          //error
  static const int c2 = 7;   //error
    static int c3 = 7;         //error
}

//correct
class A
{
public:
  A(int num):c1(num)
  {};

private:
  const int c1;
  static const int c2; 
  static int c3;
}
const int A::c2 = 7;  //不要加static
int A::c3 = 7;        //不要加statci

這裏是三種正確的初始化方法,要注意的是static在外部初始化時,不能再加上static標誌

3) const到底是不是一個重載的參考對象?
先看一個例子:


上面是重載是沒有問題的了,那麼下面的呢?

 

這是個錯誤的,編譯不通過。那麼是不是說內部參數的const不予重載呢?

再看下面的例子:

 


這個程序是正確的,看來上面的結論是錯誤的。爲什麼會這樣呢?這要涉及到接口的透明度問題。
按值傳遞時,對用戶而言,這是透明的,用戶不知道函數對形參做了什麼手腳,在這情況下進行重載是沒有
意義的,所以規定不能重載!

當指針或引用被引入時,用戶就會對函數的操作有了一定的瞭解,不再是透明的了,這時重載是有意義的,所以規定可以重載。

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