一. const 的作用
(1) 可以定義 const 常量
const int Max=100;
int Array[Max];
(2) 可以保護被修飾的東西,防止意外的修改,增強程序的健壯性
如果在函數體內修改了i,編譯器就會報錯;
(3) 爲函數重載提供了一個參考
- {
- ......
- void f(int i) {......}//一個函數
- void f(int i)const {......}//上一個函數的重載
- ......
- };
(4) 可以節省空間,避免不必要的內存分配
- const doulbe Pi=3.14159; //此時並未將Pi放入ROM中
- ......
- double i=Pi; //此時爲Pi分配內存,以後不再分配!
- double I=PI; //編譯期間進行宏替換,分配內存
- double j=Pi; //沒有內存分配
- double J=PI; //再進行宏替換,又一次分配內存!
const定義常量從彙編的角度來看,只是給出了對應的內存地址,而不是象#define一樣給出的是立即數,所以,const定義的常量在程序運行過程中只有一份拷貝,而#define定義的常量在內存中有若干個拷貝
(5) 提高了效率
編譯器通常不爲普通const常量分配存儲空間,而是將它們保存在符號表中,這使得它成爲一個編譯期間的常量,沒有了存儲與讀內存的操作,使得它的效率也很高。
二. 使用 const
(1) 修飾一般常量,常數組,常對象
修飾符const可以用在類型說明符前,也可以用在類型說明符後。 例如:
- int const x=2;
- const int x=2;
- //常數組
- int const a[5]={1, 2, 3, 4, 5};
- const int a[5]={1, 2, 3, 4, 5};
- //常對象
- class A;
- const A a;
- A const a;
(2) 修飾指針
- int const *A;//const修飾指向的對象,A可變,A指向的對象不可變
- int *const A;//const修飾指針A, A不可變,A指向的對象可變
- const int *const A;//指針A和A指向的對象都不可變
<<effective C++>>上有個好記的方法:const在*號左邊修飾的是指針所指的內容;const在*號右邊修飾的是指針。
簡單記就是:左內容,右指針。
也可以這樣理解:先忽略類型名,然後看const離哪個近,就修飾誰。
如:const [int] *p; //先去掉int,這時const 修飾*p,p是指針,*p是指針指向的對象,不可變
(3) 修飾引用
(4) 修飾函數的返回值
const修飾符也可以修飾函數的返回值,返回值不可被改變,格式如下:
const int Fun1();
const MyClass Fun2();
(5) 修飾類的成員函數
const修飾符也可以修飾類的成員函數,格式如下:
- {
- public:
- int Fun() const;
- .....
- };
class A
- {
- public:
- A(int i=0):test(i) {} //初始化列表
- private:
- const int test;
- }
(6) 在另一連接文件中引用const常量
- externconstint j=10; //錯誤!常量不可以被再次賦值
(1) 如何初始化類內部的常量?
方法1:初始化列表:
方法2: 外部初始化
(2) 放在類內部的常量有什麼限制?
這裏是三種正確的初始化方法,要注意的是static在外部初始化時,不能再加上static標誌。
3) const到底是不是一個重載的參考對象?
先看一個例子:
這是個錯誤的,編譯不通過。那麼是不是說內部參數的const不予重載呢?
再看下面的例子:
這個程序是正確的,看來上面的結論是錯誤的。爲什麼會這樣呢?這要涉及到接口的透明度問題。
按值傳遞時,對用戶而言,這是透明的,用戶不知道函數對形參做了什麼手腳,在這情況下進行重載是沒有意義的,所以規定不能重載!
當指針或引用被引入時,用戶就會對函數的操作有了一定的瞭解,不再是透明的了,這時重載是有意義的,所以規定可以重載。