new、delete是運算符
malloc()函數只負責留出一塊必定大小的內存,它不知道或關心對象自己。調用new不只會分配正確大小的內存,還會調用相應的構造函數以構建對象。
free()和delete與上面相似,delete會調用析構函數清理對象。數組
const size_t size = 4; Simple** mySimplePtrArray = new Simple*[size]; for (size_t i = 0; i < size; i++) { mySimplePtrArray[i] = new Simple(); } for (size_t i = 0; i < size; i++) { delete mySimplePtrArray[i]; } delete [] mySimplePtrArray; mySimplePtrArray = nullptr;
char** board = new char[i][j]; // 錯誤!多維數組內存佈局不是連續的,因此基於堆棧的多維數組分配足夠內存的方法是不正確的
// 正確示範 char** allocateCharBoard(size_t x, size_t y) { char** myArray = new char*[x]; for (size_t i = 0; i < x; i++) { myArray[i] = new char[y]; } return myArray; } void releaseCharBoard(char** myArray, size_t x) { for (size_t i = 0; i < x; i++) { delete [] myArray[i]; } delete [] myArray; }
// 使用標準智能指針unique_ptr和shared_ptr時須要頭文件<memory> // 建立unique_ptr void couldBeLeaky() { Simple* mySimplePtr = new Simple(); mySimplePtr -> go(); // 若是拋出異常,下面delete則不會執行,會致使內存泄漏 delete mySimplePtr; } void notLeaky() { auto mySimpleSmartPtr = make_unique<Simple>(); // 若是構造函數須要參數,放在()裏便可 mySimpleSmartPtr -> go(); } // 使用unique_ptr // a get()方法可用於直接訪問底層指針 void processData(Simple* simple) {}; auto mySimpleSmartPtr = make_unique<Simple>(); processData(mySimpleSmartPtr.get()); // b reset()可釋放底層指針並改爲另外一個指針 mySimpleSmartPtr.reset(); // 釋放並賦值爲nullptr mySimpleSmartPtr.reset(new Simple()); // 釋放並設置爲一個新指針 // c release()斷開與底層指針的鏈接,將智能指針設置爲nullptr Simple* simple = mySimpleSmartPtr.release(); delete simple; simple = nullptr; // d 建立一個C風格數組 auto arr = make_unique<int[]>(10);
// 建立shared_ptr auto smartPtr = make_shared<Simple>(); // a 和unique_ptr同樣可用於存儲動態分配的C風格數組的指針 // b 也支持get()和reset(),惟一的區別是當調用reset()時,因爲引用計數,僅在最後的shared_ptr銷燬或重置時才釋放底層資源 // c 不支持release(),可以使用use_count()來檢索同一資源的shared_ptr實例數量 // d 引用計數避免了雙重刪除