###1,描繪記憶體 ###2,new/malloc 與 delete/free new、delete是運算符 malloc()函數只負責留出一塊一定大小的記憶體,它不知道或關心對象本身。調用new不僅會分配正確大小的記憶體,還會調用相應的構造函數以構建對象。 free()和delete與上面類似,del ...
1,描繪記憶體
2,new/malloc 與 delete/free
new、delete是運算符
malloc()函數只負責留出一塊一定大小的記憶體,它不知道或關心對象本身。調用new不僅會分配正確大小的記憶體,還會調用相應的構造函數以構建對象。
free()和delete與上面類似,delete會調用析構函數清理對象。
3,指針數組的動態記憶體分配與釋放
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;
4,多維數組的動態記憶體分配與釋放
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;
}
5,智能指針
// 使用標準智能指針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 引用計數避免了雙重刪除