C++動態記憶體管理——new/delete
1.c語言的動態記憶體管理
- malloc:動態開闢指定大小的空間,返回值是void* ,所以要自己指定返回的資料型別
- int *ptr = (int*) malloc (10*sizeof(int));
- calloc:動態開闢指定大小的空間,與malloc不同的是它會進行初始化
- int* ptr = (int*)calloc(10,sizeof(int));
- realloc: 為動態開闢的空間調整大小,如果原空間後有足夠大的空間,之間在後面開闢。如果原空間後的空間不夠大,它會開闢一塊空間,將原來的資料拷貝過來,並釋放原來的空間
int *ptr = (int*) malloc (10*sizeof(int));
realloc(ptr,100*sizeof(int));
- free:動態開闢的空間一定要記得釋放,否則可能導致記憶體洩漏(指標丟了,記憶體還在)
動態開闢的記憶體都在堆上,堆上的空間由程式設計師手動開闢,手動釋放。
2.c++的動態記憶體管理:
c++通過new/delete動態管理記憶體
- new/delete動態管理物件
- new[]/delete[]動態管理物件陣列
- new做了倆件事:
- 呼叫operator new分配空間
- 呼叫了建構函式初始化物件
- delete做了倆件事
- 呼叫解構函式權力物件
- 呼叫operator delete釋放空間
- new[N]
- 呼叫operator new分配空間
- 呼叫N次建構函式分別初始化每個物件
- delete[N]
- 呼叫N次解構函式清理物件
- 呼叫operator delete釋放空間
void Test()
{
int *p1 = new int;//動態分配4位元組(1個int)的空間單個資料
int *p2 = new int(3);//動態分配4位元組(1個int)的空間並初始化
int *p3 = new int[3];//動態開闢12個位元組(3個int)的空間
delete p1;
delete p2;
delete[] p3;
}
注意:malloc和free,new/delete,new[]/delete[]要配對使用,否則可能出現記憶體洩漏甚至崩潰的問題
問:為什麼c++不能使用mallco/free來動態管理記憶體呢?
答:c語言是程式導向的語言,如果函式出錯返回錯誤碼(malloc/free出錯返回錯誤碼)
c++面對物件程式設計,出錯會拋異常
3.c++的其他記憶體管理介面
- void* operator new(size_t size);
- void operator delete(size_t size);
- void *operator new[](size_t size);
- void operator delete[](size_t size);
標準庫對函式operator new和operator delete的命名容易讓人誤解,與其他operator函式(如operator=)不同,他這些函式並不是對new和delete的過載,只是malloc和free的 一層封裝,實際上我們不能對new和delete過載
- operator new/operator delete;operator new[]/operator delete[]和malloc/free用法一樣
- 他們只負責分配空間,不會呼叫物件建構函式/解構函式來初始化/清理物件
- 實際上operator new和operator delete只是malloc和free的 一層封裝
4.maollc/free與new/delete的區別,聯絡
- 他們都是動態管理記憶體的入口
- malloc/free是函式,new/delete是操作符
- malloc要手動計算開闢空間的帶下,new開闢空間的大小由系統計算
- malloc/free不呼叫構造/解構函式,new/delete呼叫建構函式/解構函式進行初始化和函式清理
- malloc失敗返回錯誤碼,new失敗拋異常
5.malloc/free,new/delete,new[]/delete[]不匹配使用會出現哪些問題?
1)內建型別
- 不匹配使用也不會出現程式出錯、崩潰等問題
- 他們不需要呼叫構造/解構函式,不用儲存count,所以不會出現訪問記憶體出錯的問題
2)自定義型別:
- 不呼叫建構函式,不會崩潰
- 呼叫建構函式,會崩潰,因為要儲存count ,容易出現記憶體訪問出錯
- 編譯器會自動優化,如果自定義型別中沒有定義構造/析構,或者構造/解構函式內部什麼都沒有做,就不會多開闢用來儲存count的4個位元組
以下為內建型別的驗證(不匹配使用不會出錯,但是我們仍建議配對使用):
void Test()
{
int *p1 = new int;
int *p2 = new int(3);
int *p3 = new int[3];
int *p4 = (int*)malloc(sizeof(int));
delete[] p1;
//free(p1);
delete p2;
//free(p2);
//delete p3;
free(p3);
delete p4;
}
自定義型別:
class AA
{
public:
AA(size_t size = 10)
:_size(size)
, _a(0)
{
cout << "AA()" << endl;
}
~AA()
{
cout << "~AA()" << endl;
if (_a)
{
delete[] _a;
_a = 0;
_size = 0;
}
}
private:
int* _a;
size_t _size;
};
情況一:new
void Test()
{
AA* p1 = new AA;
delete p1;
//正確
//delete[] p1;
//錯誤,因為delete[]對應new[],new[]在開闢空間的時候多加了4,delete[]就會-4向前面四個位元組去取,所以會出錯
free(p1);
//正確,但是沒有呼叫解構函式
}
情景二: new(3),和情景一情況一樣,只是多了初始化
void Test()
{
AA* p2 = new AA(3);
delete p2;
//正確
//delete[] p2;
//程式出錯,因為delete[]對應new[],new[]在開闢空間的時候多加了4,delete[]就會-4向前面四個位元組去取,所以會出錯
//free(p2);
//正確,但是沒有呼叫解構函式
}
情景三:
void Test()
{
AA* p1 = new AA;
AA* p2 = new AA(3);
AA* p3 = new AA[3];
delete p1;
delete p2;
delete[] p3;
//正確
//delete p3;
//錯誤,delete直接跳過開始4位元組從後面開始釋放,所以前面的四個位元組並沒有釋放,delete[]從new[]多建立的4個位元組處開始釋放
//free(p3);
//程式崩潰
}
場景四:
void Test()
{
AA* p4 = (AA*)malloc(sizeof(AA));
free(p4);//正確
delete p4;//解構函式什麼都不做時正確
delete[] p4;//錯誤
}
相關文章
- C++記憶體管理:new / delete 和 cookieC++記憶體deleteCookie
- 記憶體(new delete )記憶體delete
- new、delete、記憶體分配 的底層原理delete記憶體
- c++動態記憶體管理與智慧指標C++記憶體指標
- C++動態記憶體管理與原始碼剖析C++記憶體原始碼
- C++動態記憶體分配C++記憶體
- C和C++的動態記憶體管理的區別C++記憶體
- C++ 指標動態記憶體分配C++指標記憶體
- C++記憶體管理C++記憶體
- 從預設解構函式學習c++,new,delete,記憶體洩漏,野指標函式C++delete記憶體指標
- C語言之動態記憶體管理C語言記憶體
- C malloc() free(), C++ new() delete()C++delete
- C++記憶體管理剖析C++記憶體
- C++ 動態記憶體分配與名稱空間C++記憶體
- 動態記憶體分配記憶體
- C++記憶體管理:簡易記憶體池的實現C++記憶體
- 【記憶體管理】Oracle AMM自動記憶體管理詳解記憶體Oracle
- 軟體測試學習教程——過載new或delete來檢測記憶體洩漏delete記憶體
- 【記憶體管理】Oracle如何使用ASMM自動共享記憶體管理記憶體OracleASM
- 記憶體管理 記憶體管理概述記憶體
- golang手動管理記憶體Golang記憶體
- 記憶體管理篇——實體記憶體的管理記憶體
- 【C/C++】4.C++的記憶體管理C++記憶體
- C++ - 二級指標動態記憶體申請與釋放C++指標記憶體
- 【記憶體管理】記憶體佈局記憶體
- return new物件造成溢位記憶體物件記憶體
- c++動態記憶體智慧指標及weak_ptr用法的理解C++記憶體指標
- 【C++】 外傳篇 3_動態記憶體申請的結果C++記憶體
- 記憶體管理兩部曲之實體記憶體管理記憶體
- Java的記憶體 -JVM 記憶體管理Java記憶體JVM
- Go:記憶體管理與記憶體清理Go記憶體
- JVM學習-自動記憶體管理JVM記憶體
- JVM學習筆記——自動記憶體管理JVM筆記記憶體
- 記憶體管理兩部曲之虛擬記憶體管理記憶體
- C++記憶體掃描C++記憶體
- ABAP Memory Inspector 裡對動態記憶體物件的記憶體消耗度量方式記憶體物件
- JavaScript 記憶體管理JavaScript記憶體
- iOS 記憶體管理iOS記憶體