C++ 語言可以用const
來定義常量唐础,也可以用#define
來定義常量。但是前者比后者有更多的優(yōu)點:
-
const
常量有數(shù)據(jù)類型矾飞,而宏常量沒有數(shù)據(jù)類型。編譯器可以對前者進行類型安全檢查呀邢。而對后者只進行字符替換洒沦,沒有類型安全檢查,并且在字符替換可能會產(chǎn)生意料不到的錯誤(邊際效應)价淌。 - 有些集成化的調(diào)試工具可以對
const
常量進行調(diào)試申眼,但是不能對宏常量進行調(diào)試。規(guī)則5-2-1:在C++ 程序中只使用const 常量而不使用宏常量蝉衣,即const
常量完全取代宏常量括尸。
2.實現(xiàn)機制
宏是預處理命令,即在預編譯階段進行字節(jié)替換病毡。const
常量是變量濒翻,在執(zhí)行時const
定義的只讀變量在程序運行過程中只有一份拷貝(因為它是全局的只讀變量,存放在靜態(tài)存儲區(qū)的只讀數(shù)據(jù)區(qū)啦膜。根據(jù)C/C++語法有送,當你聲明該量為常量,即告訴程序和編譯器僧家,你不希望此量被修改雀摘。 程序的實現(xiàn),為了保護常量八拱,特將常量都放在受保護的靜態(tài)存儲區(qū)內(nèi)阵赠。凡是試圖修改這個區(qū)域內(nèi)的值,都將被視為非法肌稻,并報錯清蚀。 這不能理解為凡是字符串都是放在靜態(tài)存儲區(qū)域的。這個跟數(shù)據(jù)類型沒有關系灯萍,而是這個量是變量還是常量的問題轧铁。例如,一個字符串變量就是可以被修改的旦棉。 這種靜態(tài)存儲區(qū)域的保護機制是由編譯器實現(xiàn)的齿风,而非存儲該值的內(nèi)存的電器屬性药薯。換言之,實質(zhì)上內(nèi)存永遠都可以被用戶隨意修改救斑,只是編譯器給用戶的代碼注入了一些自己的保護代碼童本,通過軟件手段將這段內(nèi)存軟保護起來。這種保護在匯編級別可以輕松突破脸候,其保護也就無效了穷娱。
3.用法區(qū)別
#define
宏定義和const
常變量區(qū)別:
- 1.
#define
是宏定義,程序在預處理階段將用#define
定義的內(nèi)容進行了替換运沦。因此程序運行時泵额,常量表中并沒有用#define
定義的常量,系統(tǒng)不為它分配內(nèi)存携添。const
定義的常量嫁盲,在程序運行時在常量表中,系統(tǒng)為它分配內(nèi)存烈掠。 - 2.
#define
定義的常量羞秤,預處理時只是直接進行了替換。所以編譯時不能進行數(shù)據(jù)類型檢驗左敌。const
定義的常量瘾蛋,在編譯時進行嚴格的類型檢驗,可以避免出錯矫限。 - 3.
#define
定義表達式時要注意“邊緣效應”哺哼,例如如下定義:
#define N 2+3; //我們預想的N值是5,我們這樣使用N
int a = N/2; //我們預想的a的值是2
可實際上a的值是3叼风。原因在于在預處理階段幸斥,編譯器將a = N/2
處理成了a = 2+3/2;
這就是宏定義的字符串替換的“邊緣效應”因此要如下定義:#define N (2+3)
。const
定義的表達式則沒有上述問題咬扇。const
定義的常量叫做常變量原因有二:
-
const
定義常量像變量一樣檢查類型甲葬; -
const
可以在任何地方定義常量,編譯器對它的處理過程與變量相似懈贺,只是分配內(nèi)存的地方不同经窖。