malloc與free是C++/C語言用于動態內存分配的標準庫函數,因此在 C++ 中也可以使用,但是因為缺乏類型安全性(需要手動轉換指針類型)和自動內存管理的功能,通常不推薦在C++中使用。對于非內部數據類型的對象而言,使用maloc/free無法滿足動態對象的要求。對象在創建的同時要自動執行構造函數,對象在消亡之前要自動執行析構函數。由于malloc/free是庫函數,不在編譯器控制權限之內,不應當去執行構造函數和析構函數的任務。因此往往還需要定義初始化和銷毀清除功能的函數來執行構造和析構,而使用new與delete則覆蓋了這些功能。
new/delete是C++的運算符,用于申請動態內存和釋放內存,同時增加了類型安全性,并且可以調用構造函數和析構函數,完成初始化與清理釋放的工作,能夠兼容C++的異常安全機制,但未正確處理異常時,會導致未定義行為。malloc/free與new/delete都應當成對出現,存在分配內存,就應當及時銷毀。當然,如果用free釋放”new創建的動態對象”,或用delete釋放”malloc申請的動態內存”,那么該對象因無法執行析構函數而可能導致程序出錯。
智能指針是現代 C++ 中用來自動管理指針所指向的對象生命周期的對象。它們通過在構造時獲取對動態分配對象的所有權,并在析構時釋放這個所有權來管理內存。可以有效地避免內存管理和生命周期管理中的常見錯誤。
其中:
shared_ptr支持共享所有權,允許多個shared_ptr對象共享同一個資源。當最后一個指向該資源的shared_ptr對象銷毀時,資源才會被釋放。weak_ptr是shared_ptr的弱引用,指的是可以使用該對象,但是沒有所有權,由真正擁有其所有權的來負責釋放。不增加引用計數,通常用于解決shared_ptr循環引用的問題。
unique_ptr表示獨占所有權的智能指針,意味著同一時間內只能有一個unique_ptr 對象擁有一個給定資源的所有權。當unique_ptr對象銷毀或綁定到一個新的資源時,其原來擁有的資源會被釋放。unique_ptr性能優于shared_ptr且內存占用上小于shared_ptr,因為shared_ptr在拷貝或者釋放時候,都需要操作引用計數,需要維護它指向的對象的線程安全引用計數和一個控制塊,這使得它比unique_ptr更重量級。
因此如果程序要使用多個指向同一個對象的指針,應選擇shared_ptr。如果函數使用new分配內存,并返還指向該內存的指針,將其返回類型聲明為unique_ptr是不錯的選擇。這樣,所有權轉讓給接受返回值的unique_ptr,而該智能指針將負責調用delete。
常用的初始化shared_ptr兩種代碼如下:
std::shared_ptr<Type> p1 = new Type;
std::shared_ptr<Type> p2 = std::make_shared<Type>();
new方式的初始化方式共有兩次內存分配操作:new Type分配對象和為p1分配控制塊(control block),控制塊用于存放引用計數等信息。而make_shared初始化方式只有一次內存申請(是由make_shared的函數實現決定的),所以建議使用make_shared方式進行初始化。