摘 要:const變量和內聯函數是C++語言特有的語法,其功能和使用方法與C語言的宏定義有很多相似之處。本文簡述了const變量和內聯函數的功能與使用方法,通過與宏定義對比教學,引導學生在掌握了宏定義的基礎之上,更深刻地理解const變量和內聯函數的特點。
關鍵詞:const變量;內聯函數;宏定義;教學
一、引言
C++語言完全兼容C語言,具有C語言的全部功能。單純就程序語法的學習而言,如果已經學習了C語言,那么再學習C++會輕松一些,只需要重點學習C++新增的語法知識即可,例如類、對象和繼承等等。const變量和內聯函數也是C++新增的語法,其功能和使用方法與C語言的宏定義有很多相似之處,但是又有宏定義所不具備的優點。在C++語言授課中有意識地與C語言的宏定義對照學習,通過引導學生進行對比分析,體會C++語法的優點,從而有效掌握新增知識點。
二、const變量
變量是程序運行期間,其值可以改變的量。變量有名字,實際代表內存中某一段存儲空間,其中可以存放數據即變量的值,存儲空間的大小由變量的數據類型決定。在C++程序中,所有的變量在使用之前都必須要定義。變量的定義主要是指出變量的名稱,確定變量的類型,并讓系統為其分配相應的內存空間。變量定義語句的一般形式為:
類型 變量名1,變量名2,……;
const變量又稱為只讀變量,其定義形式與普通變量極為相似,只不過是在數據類型的前面加上const而已。例如:
const float PI=3.14;
const變量必須在定義的時候立刻初始化,而且在程序執行期間,其值不能夠被修改。在本例中PI用來存放圓周率π的值,它的值固定為3.14。C++語言的const變量其用法與C語言的符號常量,頗有相似之處。所謂符號常量,就是用標識符表示的常量。C語言允許用宏定義的方式描述符號常量,例如:
#define PI 3.14
宏定義是指用#define開頭的預處理命令,有無參數和有參數兩種形式。它的作用是用一個標識符來代表一個字符串,標識符稱為宏名,字符串稱為宏體。在編譯預處理時,把程序中該宏定義之后的所有宏名都用宏體替換,這稱為宏替換。在本例中PI稱為宏名,3.14稱為宏體。在程序中出現標識符PI,即表示常量3.14。
表面上看const變量的實際效果似乎等同于符號常量,所以往往有學生會提問,既然用宏定義的方式就可以描述符號常量,為什么C++語言還要引入const變量呢?這時就需要給學生解釋強類型語言的概念。宏定義只是在程序編譯之前做簡單的字符替換,即用3.14替代PI,并不進行數據類型的檢查,這樣有可能會出現一些編譯階段所無法發現的錯誤;而const變量除了其值不能被修改之外,其它方面完全與變量一樣。C++作為一種強類型語言,在操作之前,編譯器會對const變量進行類型合法性檢查,從而有可能在編譯階段就發現一些錯誤。這樣做既降低了程序調試的難度,又提高了程序的可靠性。就此可以乘勢建議學生在C++程序中,盡量用const變量,少用宏定義描述的符號常量。
三、內聯函數
函數是C程序實現模塊化結構的主要手段,也是C++程序描述對象行為的主要方法。函數可以提高程序代碼的可讀性和重用性,便于調試和維護。但是函數調用也增加了額外的系統開銷,例如在程序執行轉移時,為函數的變量分配內存的存儲空間,保存主調函數的執行點(現場)以及一些參數和寄存器的值等。C++語言允許程序員將那些代碼較短、調用頻繁的函數定義為內聯函數,以提高程序運行的效率。內聯函數的作用是,在調用它時并不發生通常的程序執行轉移,而是把函數體的語句插入到函數調用處。inline是C++語言的關鍵字,用來定義內聯函數。例如定義一個函數area,其功能是計算正方形的面積。代碼如下:
inline float area(float x)
{
return x*x;
}
從編寫程序的角度來看,內聯函數的定義和調用與普通函數的定義和調用幾乎沒有什么差別,只不過內聯函數在定義時多了一個inline關鍵字而已。程序運行時內聯函數并沒有發生真正的函數調用,而是類似于粘貼動作一樣,自動把函數體插入到每一個函數調用的位置。因此內聯函數是以犧牲程序的空間為代價,來換取程序運行的時間。如果學生已經學習過C語言的帶參數的宏定義,一定會發現它與內聯函數非常相似。表面上看都具有函數的形式,有形參,使用時也是插入到調用之處等等。例如:
#define area(x) x*x
定義了一個帶參數的宏定義,在程序中如果出現area(3.2),將被自動替換為3.2*3.2。通過內聯函數與帶參數的宏定義的對比學習,學生可能會問,既然帶參數的宏定義與內聯函數如此相似,為什么C++語言還要提供內聯函數這種機制呢?這就需要教師進行深入分析,內聯函數雖然執行機制與帶參數的宏定義很相似,但它畢竟是C++的函數,調用時C++編譯器會對它進行類型檢查和參數檢查,計算實參的值,并依次賦給形參。而帶參數的宏定義在使用時,只是作簡單的替換工作,即用宏體替代宏名。這種方式是不進行任何檢查的,因而會帶來一些隱患。
例如在程序中出現area(1+2),我們預期的結果顯然是9。但是替換之后變為1+2*1+2,結果卻是5。可能有的學生已經看出來了,只要帶參數的宏定義的形參帶上括號,就能夠避免類似的問題,即寫為:#define area(x) (x)*(x)。此時教師可以接著提問,難道這樣做了之后,就可以高枕無憂了嗎?如果在程序中出現8/area(2),我們預期的結果顯然是2。但是替換之后變為8/(2)*(2),結果卻是8。進一步啟發學生,即可得出結論,實際上要想做到萬無一失,只能寫成以下形式:#define area(x) ((x)*(x))。因此相比較而言,內聯函數沒有帶參數的宏定義所可能有的副作用,是一種執行效率較高,也較為安全的語法。通過案例對比分析,學生就會較為容易地接受內聯函數,并樂于在C++程序中采用。
四、結語
相對類、對象和繼承而言,const變量和內聯函數并不是C++語言的核心語法。但是通過與C語言的宏定義對比教學中,還是可以讓學生深刻理解const變量和內聯函數的特點,并逐漸體會C++語言的優點,在程序中熟練運用。
參考文獻:
[1] 王曉東. C++程序設計簡明教程(第二版)[M].北京:中國水利水電出版社, 2017.
[2] 鄭莉. C++語言程序設計[M].北京:清華大學出版社, 2001.
[3] 江義華. C/C++完美演繹[M].北京:中國水利水電出版社, 2001.