ZWeily的小品文(三)C++入門教程(2) (轉)
“叮……叮……叮……”
一陣電話鈴聲把我從夢裡吵醒,是哪個可惡的傢伙啊,連覺都不讓別人睡好,難得雙休日不用加班,真是#%%¥# ……(此處省略213字的抱怨)
“喂!誰啊?”還沒睡醒,腦袋有點暈,於是語氣也有點不客氣。
“師傅早!”Young的語氣到是十分客氣的樣子。
“原來是你啊!這麼早打電話找我幹什麼啊?”
“很早嗎?”
我看了一下鬧鐘,“才七點五十啊!”
“啊?你果然沒睡醒哦。看看清楚嘛……”Young故意拖長了最後一個字,似乎在給我改正的機會。
我揉了揉眼睛,再看了一下邊上那個小鬧鐘,啊,原來我把長針和短針看反了,已經十點四十了。
“喔,抱歉!被你說中了,我的確沒睡醒,昨天晚上,哦,不對,是今天早上3點才睡的。不過今天是週六啊,睡晚點也沒關係吧?”沒睡醒,腦子有點糊,一下子找不出什麼體面一點的藉口,還是實話實說為好。
“呵呵,沒關係啦,幹這行的似乎都是這樣的,我知道的啦!”
“恩,那你今天找我有什麼事啊?”還是轉個話題為好。
“上次你給我講的東西我都懂了,所以,我想問你今天有沒有空啊?可不可以繼續我們的課程啊?”Young的語氣很誠懇。
“今天?讓我看看。喔…… 今天我沒什麼安排,那要麼等一下到公司碰面?”
“好啊!那就這樣說定咯!”
“好啦,不會放你鴿子的啦,放心啦!”
“恩,那我就先去公司等你,你快點來哦。”
“好的,就這樣,拜拜!”
掛了電話,趕忙起床。
……(三十分鐘後到了公司)
一進我們小組的工作室,就看見Young已經坐在我的位子上,捧著本書,似乎是《The C++ Programming Language》。
“你這麼快就來啦?沒吃早飯吧?”我剛想叫她,結果她已經看到我了,又把我的臺詞搶了。
“恩,還沒吃。一般我週末都只吃兩頓的。”
“那好,等一下一起吃午飯吧,還是我請哦!”
“你這個徒弟到是夠乖的,總是請師傅吃飯啊。恩,這頓飯就算補我的睡眠了,就不責怪你那麼早打電話把我吵醒了。”
“呵呵,實在抱歉啦,我也不知道這麼晚了,您老人家還在夢中神遊。”
“老人家?咳咳…… 注意用詞!我看上去有那麼老嗎?”
“沒有啦,我用這個詞的目的只是為了表示對您的尊敬”Young一臉鬼笑,我也真是那她沒辦法。
“好吧,那就開始今天的課程吧。恩,讓我想想今天該教你點什麼……”說這句話的時候,腦中閃過一個個C++中的特性和關鍵字,“我們就從C++裡面的基本型別講起吧。”
“好啊。喔,我知道C++支援原來C裡面的所有的基本型別,就像int、char、float、double等等。這些東西的用法和原來C裡面一樣吧。”Young在說這些的時候,眼神中帶著一點自信。
“恩,基本正確。”
“啊?難道還有不同?”自信的眼神沒了,Young又進入了疑問的狀態。
“的確還有不同。就這些C++內建的基本型別而言,C++支援C中的使用方法,但是還增加了一點特性。我問你,怎麼對一個int型別初始化?”
Young很有自信的在螢幕上打出:
int a = 3; //定義int型別變數a,並且初始化為3
“正確,無論在C和C++中,這樣做總是正確的。但是,你知道另外一種初始化的方法嗎?”
“……不知道。”
“其實還可以這樣初始化。”我在螢幕上打出:
int a(3); //定義int型別變數a,並且用構造語法初始化為3
“哦,原來還可以這樣啊?那這個和原來的方式有什麼不同呢?”
“其實這種方式對於一般的內建資料型別而言,基本上沒有區別的。但是這種方式對於C++而言,有著很重要的價值,否則,它也不會存在啊。例如下面這個例子。”
int* p = new int; //定義一個指向int型別的指標,並且為它動態分配一塊
*p = 3; //將p指向的賦值為3
“這樣寫的確沒有什麼問題,但是我們可以利用建構函式語法將這兩行程式碼變成一行。就象下面這樣。”
int* p = new int(3);
“這樣就既完成了動態分配,也賦了初值。還記得C裡面用來動態申請記憶體的函式嗎?”
“記得,就是那個malloc()!”
“是的。這個函式和C++裡的new這個運算子的本質區別就在於new會自動地去物件的建構函式,而malloc不會。這也是new的優點,它能保證動態生成的物件在生成的時候就被初始化,這個特點可以避免很多可能發生的錯誤。”
“我沒聽錯吧,你說new是一個運算子?”
“沒錯,new是一個operator,其實C++裡的運算子就象函式一樣,其實就是一種特殊的函式。恩,等到以後給你講運算子過載的時候我再給你詳細解釋。”
“哦,大致聽懂了。你剛才說的在建立一個物件的時候沒有初始化所帶來的麻煩,我以前在學C的時候碰到過。恩,我會記住這點的。”
“好,接下去我們講const這個關鍵字的使用。”
“const?這個關鍵字我在看書的時候看到過,而且被它搞暈了,一想到這個就覺得不爽。”Young似乎有點沮喪。
“是不是關鍵問題出在和指標的關係上啊?”
“是啊!原來師傅你也深有體會啊!”
“你這張嘴真是不饒人啊,厲害!算了,我不和你計較。還是先說區分方法。其實要搞清楚它和指標的關係很簡單,只要看const這個關鍵字出現在*之前還是*之後。如果出現在*之前,就表示這個指標所指向的物件是const的;而如果出現在*之後,那麼這個指標本身就是const的。當然,我想對於前後都有這種情況就不用我說了吧?”
“喔!原來是這樣,這回知道了!”
“還有,由於const的物件是不能被賦值的,所以const物件一定要初始化。”
“恩,記住了。”
“順便教你一種寫法,可以直接從字面上讀出const和指標的關係。就像這樣”
char *const cp; //const pointer to char
char const* pc; //pointer to const char
“運用前面教你的方法,很容易區別出這兩個指標的不同。你試著用從右到左的順序將它念出來。”
“從右到左?倒著念?好的,我試試。第一個是:‘cp const * char’,第二個是:‘pc * const char’”
“恩,接下去,試著在變數名之後加上‘is a ’,再將‘*’改成‘pointer to ’,再把它念一遍。”
“好的。第一個是:‘cp is a const pointer to char’,第二個是:‘pc is a pointer to const char’。啊!這樣不就區分出兩者的區別了啊!好神奇啊!”
“對了,用這種方式來書寫,能夠直接讀出兩者的區別。對於第二個來說,也可以將const這個關鍵字放在最前面,對於而言,‘const char* pc;’和‘char const* pc;’是一樣的,可是後者對於員而言更容易讀懂。”
“這回終於搞清楚了,以後寫程式的時候我一定會注意的,寫得清楚能夠給別人方便,也給自己方便。”
“不錯!能夠領悟到這點很不錯!要記住,‘從工程的角度而言,程式的清晰性是最重要的!’”
“恩,記住了!”
“最後我們再來看看引用(reference)和指標(pointer)的區別和聯絡。引用又可以稱作為變數別名它在它作用域的任何地方都代表其最初被初始化的那個物件。例如,”
int a = 3;
int& r = a;
“在這以後的程式碼中,r就是變數a。兩者完全一樣。對於r的任何操作,其實都是作用在a的上面的。而指標我想你已經在學C的時候學過了,應該熟悉了它的用法和特點。為了讓函式能夠改變呼叫時送入的變數的值,我們就要使用指標或者引用。例如,”
void s(int& a, int& b) //利用引用,a和b
{
int t;
t = a;
a = b;
b = t;
}
void swap(int* a, int* b) //利用指標,交換a和b
{
int t;
t = *a;
*a = *b;
*b = t;
}
“看到指標和引用的區別了嗎?指標在使用其指向的變數的時候,需要使用*這個解引用(dereference)運算子;而引用就是其引用的物件的別名,直接使用就可以了。但是要注意,利用引用的特點,在函式里改變引數物件的值的做法,缺少可讀性,比較容易出錯,所以在寫這樣的程式碼的時候一定要小心。使用引用或者指標來傳遞引數其實還有一個優點,就是能夠提高程式的,避免複製建構函式和解構函式的呼叫。所以,往往比較常見的是‘const T& ref’這種形式作為形參,T代表C++某種內建型別或者自定義型別。最後還有一點要注意的就是,引用在初始化之後就不能改換引用的物件,也就是不能再次引用其他物件,所以,引用在定義的時候就必須被初始化。”
“恩,懂了。今天你教了我好多東西哦!喔…… 時間不早了,該去吃飯了,難道你不餓嗎?”
我一看螢幕上的時間,天哪!都已經下午一點多了。此時,我的肚子也很配合的叫了一下。
“看你餓的!那就快點走吧!”Young似乎也餓了,一直在催我。
而我,一直在想,是不是帶了這個徒弟以後,我的胃總有一天會出問題啊……
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-993204/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- C++入門教程C++
- NSIS 入門教程 (三)
- Batch入門教程(2)BAT
- uiautomator2 入門教程UI
- C++入門(2):為何還學C++?C++
- C++ 入門防爆零教程(上冊)C++
- C++入門教程(11):呼叫函式C++函式
- C++入門教程(9):while 語句C++While
- 【Android開發入門教程】三.Activity入門指南!Android
- 轉:區塊鏈入門教程區塊鏈
- [轉]Systemd 入門教程:命令篇
- Tensorflow 2.x入門教程
- C++入門教程(12):定義函式C++函式
- C++入門教程(14):過載函式C++函式
- C++入門教程之二:變數C++變數
- ARMv9的SVE/SVE2入門教程 (2)
- [2]SpinalHDL教程——Scala簡單入門
- C++入門教程(3):語句和縮排C++
- Laravel 入門教程-第三章Laravel
- Metal入門教程(二)三維變換
- 《Flask 入門教程》 第 2 章:Hello, Flask!Flask
- SparkStreaming入門教程(三)高階輸入源:Flume、KaSpark
- 埠轉發工具Rinetd詳細入門教程
- C++入門教程(20):變數、不變數和常量C++變數
- 【視訊】Entity Framework Core 2.* 入門教程Framework
- Nodejs教程30(完結):PM2入門NodeJS
- RabbitMQ 入門(三)SpringAMQP訊息轉換器MQSpringGAM
- Jwt的新手入門教程JWT
- Metal入門教程(三)攝像頭採集渲染
- Flutter小白教程系列(三) --- Dart語言快速入門FlutterDart
- GAN網路之入門教程(三)之DCGAN原理
- Flutter狀態管理:Provider4 入門教程(三)FlutterIDE
- Docker 實戰教程之從入門到提高(三)Docker
- J2SE入門(三) String深度解析
- C++入門教程(5):基本資料型別和變數C++資料型別變數
- Android入門教程 | RecyclerView使用入門AndroidView
- Spring Boot 2.x基礎教程:快速入門Spring Boot
- SpringBoot2.x入門教程:理解配置檔案Spring Boot
- C++快速入門+20201011C++