這一篇要談的是程式語言界,人人聞之喪膽的「指標」以及「記憶體管理」,先抓出常見的問題,然後在之後的文章說明如何利用 Modern C++ 來減輕痛苦。開始前,我要跟讀者分享一個觀念。
指標雖難,但還沒難到認真學習而且投入心力,還學不會的地步。不要自己嚇自己,指標這種東西,下苦心,一定學得會,千萬不要還沒開始就放棄。
弄懂指標需要投入時間,初學者切勿躁進。學指標沒有捷徑,先搞懂基本觀念,多看優質程式碼,多練習,慢慢就會開竅。
不管外行人如何「污名化」指標,指標始終是 C++ 最重要的功能之一。懂得善用指標是專業 C++ 程式師的基本功。逃避不能成專業,若沒有面對指標的決心,不要戀棧,去學其他程式語言吧。
指標讓程式師直接操控記憶體,功能強大,也因此帶來弄掛程式,甚至搞垮系統的高風險。指標相關的問題千百種,我列出幾個常見的難題:
底下程式碼示範典型的「記憶體洩漏」臭蟲:
char* buffer = (char*)malloc(128);
// ①
if (something when wrong)
return -1;
memcpy(buffer, "123456", 6);
// Do something...
free(buffer);
位置 ① 若「invalid input」為真,函數直接跳離,導致 buffer 沒有被釋放(free)。你可能會說,這麼顯而易見的錯誤,不可能沒看出來吧?就是會!
另一個問題是,該由誰負責釋放記憶體?參考以下程式碼:
Tea* tea = MakeTea();
tea->DoSomething();
delete tea; // ①
九成九,應該在 ① 那行刪除物件並釋放記憶體,但是,若 MakeTea() 回傳的是一個 Singleton 呢?若是,那麼呼叫端就不應該刪除該物件,而是由 MakeTea() 內部的機制管理。上述程式碼看不出這樣的意圖,可能一個不小心就生出一隻臭蟲。
還有一個常見的臭蟲是:使用 new 卻用 free() 釋放記憶體,或者相反。
C++11 加入了幾個好用的新組件,可用來對付指標以及記憶體管理。下一篇,我將介紹 std::unique_ptr,這個在幾乎不折損執行效能的情況下,提供物件以及記憶體管理的新方法。
TheChernoProject YouTube 頻道有一系列從入門到進階的 C++ 教學影片。關於指標,我建議看這片。