C++之內(nèi)存分配new與delete使用方式
C++ new 和 delete
在C++中,new 和 delete 是用于動(dòng)態(tài)內(nèi)存分配和釋放的運(yùn)算符。
它們?cè)试S程序在運(yùn)行時(shí)管理堆內(nèi)存,是實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)(如鏈表、樹)和靈活資源管理的基礎(chǔ)。
1. 基本語法
new 運(yùn)算符
- 分配單個(gè)對(duì)象:
Type* ptr = new Type; // 默認(rèn)初始化(內(nèi)置類型值未定義)
Type* ptr = new Type(value); // 直接初始化
Type* ptr = new Type{value}; // 列表初始化(C++11起)- 分配數(shù)組:
Type* arr = new Type[size]; // 分配包含size個(gè)元素的數(shù)組
- 值初始化:
Type* ptr = new Type(); // 值初始化為0或默認(rèn)構(gòu)造函數(shù)
delete 運(yùn)算符
- 釋放單個(gè)對(duì)象:
delete ptr; // 調(diào)用析構(gòu)函數(shù)(如有)并釋放內(nèi)存
- 釋放數(shù)組:
delete[] arr; // 釋放數(shù)組內(nèi)存,需使用[]告知編譯器釋放多個(gè)對(duì)象
2. 工作原理
new 的執(zhí)行步驟
- 內(nèi)存分配:調(diào)用
operator new(或operator new[]用于數(shù)組)分配原始內(nèi)存。 - 構(gòu)造函數(shù)調(diào)用:在分配的內(nèi)存上調(diào)用對(duì)象的構(gòu)造函數(shù)(若為類類型)。
delete 的執(zhí)行步驟
- 析構(gòu)函數(shù)調(diào)用:對(duì)對(duì)象調(diào)用析構(gòu)函數(shù)(若為類類型)。
- 內(nèi)存釋放:調(diào)用
operator delete(或operator delete[])釋放內(nèi)存。
3. 深入理解 new 和 delete
原始內(nèi)存操作
operator new 和 operator delete:
底層函數(shù),可被重載以自定義內(nèi)存分配行為。
void* operator new(size_t size); // 分配單個(gè)對(duì)象 void* operator new[](size_t size); // 分配數(shù)組 void operator delete(void* ptr); // 釋放單個(gè)對(duì)象 void operator delete[](void* ptr); // 釋放數(shù)組
示例:
void* raw_memory = operator new(sizeof(int)); // 分配原始內(nèi)存 int* ptr = static_cast<int*>(raw_memory); // 轉(zhuǎn)換為int指針 *ptr = 42; // 手動(dòng)賦值 operator delete(ptr); // 釋放內(nèi)存(不調(diào)用析構(gòu)函數(shù))
定位 new(Placement New)
在已分配的內(nèi)存上構(gòu)造對(duì)象:
void* buffer = operator new(sizeof(MyClass)); // 分配原始內(nèi)存 MyClass* obj = new (buffer) MyClass(); // 在buffer上構(gòu)造對(duì)象 obj->~MyClass(); // 顯式調(diào)用析構(gòu)函數(shù) operator delete(buffer); // 釋放內(nèi)存
4. 數(shù)組的動(dòng)態(tài)分配
分配與釋放數(shù)組
int* arr = new int[10]; // 分配10個(gè)int的數(shù)組
delete[] arr; // 釋放數(shù)組
// 多維數(shù)組
int** matrix = new int*[5]; // 分配5行
for (int i = 0; i < 5; ++i) {
matrix[i] = new int[10]; // 每行10列
}
// 釋放
for (int i = 0; i < 5; ++i) {
delete[] matrix[i];
}
delete[] matrix;數(shù)組初始化
int* arr = new int[5]{1, 2, 3, 4, 5}; // C++11起支持列表初始化在對(duì)數(shù)組進(jìn)行動(dòng)態(tài)分配時(shí),會(huì)自動(dòng)在之前多分配一塊空間用來儲(chǔ)存所要開辟的空間個(gè)數(shù),以便將來用delete釋放空間。
5.new和delete的實(shí)現(xiàn)原理
5.1 內(nèi)置類型
如果申請(qǐng)的是內(nèi)置類型的空間,new和malloc,delete和free基本類似,不同的地方是:
new/delete申請(qǐng)和釋放的是單個(gè)元素的空間,new[]和delete[]申請(qǐng)的是連續(xù)空間,而且new在申請(qǐng)空間失敗時(shí)會(huì)拋異常,malloc會(huì)返回NULL。
5.2 自定義類型
new的原理
- 調(diào)用operator new函數(shù)申請(qǐng)空間
- 在申請(qǐng)的空間上執(zhí)行構(gòu)造函數(shù),完成對(duì)象的構(gòu)造
delete的原理
- 在空間上執(zhí)行析構(gòu)函數(shù),完成對(duì)象中資源的清理工作
- 調(diào)用operator delete函數(shù)釋放對(duì)象的空間
new T[N]的原理
- 調(diào)用operator new[]函數(shù),在operator new[]中實(shí)際調(diào)用operator new函數(shù)完成N個(gè)對(duì)象空間的申請(qǐng)
- 在申請(qǐng)的空間上執(zhí)行N次構(gòu)造函數(shù)
delete[]的原理
- 在釋放的對(duì)象空間上執(zhí)行N次析構(gòu)函數(shù),完成N個(gè)對(duì)象中資源的清理
- 調(diào)用operator delete[]釋放空間,實(shí)際在operator delete[]中調(diào)用operator delete來釋放空間
6. 常見問題與注意事項(xiàng)
內(nèi)存泄漏
原因:忘記調(diào)用 delete 釋放 new 分配的內(nèi)存。
示例:
void leak() {
int* ptr = new int; // 分配內(nèi)存
// 未釋放內(nèi)存就返回
} // 內(nèi)存泄漏!懸空指針
原因:釋放內(nèi)存后仍保留指向該內(nèi)存的指針。
示例:
int* ptr = new int; delete ptr; *ptr = 10; // 懸空指針解引用,未定義行為
重復(fù)釋放
原因:多次釋放同一塊內(nèi)存。
示例:
int* ptr = new int; delete ptr; delete ptr; // 重復(fù)釋放,未定義行為
混用 delete 和 delete[]
錯(cuò)誤示例:
int* arr = new int[10]; delete arr; // 錯(cuò)誤!應(yīng)使用delete[]
對(duì)于內(nèi)置類型,程序會(huì)崩潰;而對(duì)于自定義類型,程序不會(huì)崩潰。
7. 自定義內(nèi)存管理
重載全局 operator new 和 operator delete
void* operator new(size_t size) {
void* p = malloc(size);
// 可添加內(nèi)存分配日志、性能監(jiān)控等
return p;
}
void operator delete(void* p) noexcept {
free(p);
// 可添加內(nèi)存釋放日志等
}類特定的內(nèi)存管理
class MyClass {
public:
static void* operator new(size_t size) {
// 自定義分配邏輯
return ::operator new(size);
}
static void operator delete(void* p) noexcept {
// 自定義釋放邏輯
::operator delete(p);
}
};8. 與C語言內(nèi)存管理的對(duì)比
| 特性 | C++ new/delete | C語言 malloc/free |
|---|---|---|
| 類型安全 | 自動(dòng)推導(dǎo)類型,無需強(qiáng)制轉(zhuǎn)換 | 需要顯式轉(zhuǎn)換(如 (int*)malloc()) |
| 構(gòu)造/析構(gòu)函數(shù) | 自動(dòng)調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù) | 不調(diào)用構(gòu)造/析構(gòu)函數(shù) |
| 初始化 | 支持直接初始化和列表初始化 | 僅分配內(nèi)存,不初始化值 |
| 數(shù)組語法 | 直接使用 new Type[size] | 需要計(jì)算總大?。ㄈ?malloc(size*sizeof(Type))) |
| 智能指針支持 | 與標(biāo)準(zhǔn)庫(kù)智能指針無縫配合 | 需手動(dòng)封裝為智能指針 |
malloc/free和new/delete的共同點(diǎn)是:都是從堆上申請(qǐng)空間,并且需要用戶手動(dòng)釋放。
不同的地方是:
- malloc和free是函數(shù),new和delete是操作符
- malloc申請(qǐng)的空間不會(huì)初始化,new可以初始化
- malloc申請(qǐng)空間時(shí),需要手動(dòng)計(jì)算空間大小并傳遞,new只需在其后跟上空間的類型即可, 如果是多個(gè)對(duì)象,[]中指定對(duì)象個(gè)數(shù)即可
- malloc的返回值為void*, 在使用時(shí)必須強(qiáng)轉(zhuǎn),new不需要,因?yàn)閚ew后跟的是空間的類型
- malloc申請(qǐng)空間失敗時(shí),返回的是NULL,因此使用時(shí)必須判空,new不需要,但是new需要捕獲異常
- 申請(qǐng)自定義類型對(duì)象時(shí),malloc/free只會(huì)開辟空間,不會(huì)調(diào)用構(gòu)造函數(shù)與析構(gòu)函數(shù),而new在申請(qǐng)空間后會(huì)調(diào)用構(gòu)造函數(shù)完成對(duì)象的初始化,delete在釋放空間前會(huì)調(diào)用析構(gòu)函數(shù)完成空間中資源的清理釋放
總結(jié)
new/delete 是C++動(dòng)態(tài)內(nèi)存分配的核心機(jī)制,適用于:
- 需要在運(yùn)行時(shí)確定對(duì)象生命周期。
- 實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)(如鏈表、樹)。
- 優(yōu)先使用智能指針:現(xiàn)代C++中,
std::unique_ptr和std::shared_ptr能有效避免內(nèi)存泄漏,提高代碼安全性。 - 謹(jǐn)慎手動(dòng)管理內(nèi)存:必須確保
new和delete配對(duì)使用,避免懸空指針和重復(fù)釋放。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用C/C++讀取matlab中.mat格式數(shù)據(jù)的操作
這篇文章給大家介紹了使用C/C++讀取matlab中.mat格式數(shù)據(jù)的操作,文中通過圖文結(jié)合的方式介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2023-12-12
深入c++中臨時(shí)對(duì)象的析構(gòu)時(shí)機(jī)的詳解
本篇文章對(duì)c++中臨時(shí)對(duì)象的析構(gòu)時(shí)機(jī)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
Qt?QtCreator添加自定義注釋的實(shí)現(xiàn)方法
在寫代碼的時(shí)候我們?yōu)榱艘?guī)范化,一般會(huì)加文件注釋、類注釋和函數(shù)注釋,本文主要介紹了Qt?QtCreator添加自定義注釋的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的可以了解一下2023-11-11
CMake自動(dòng)管理C/C++項(xiàng)目的實(shí)現(xiàn)
CMake是一個(gè)強(qiáng)大的構(gòu)建系統(tǒng),用于跨平臺(tái)管理C/C++項(xiàng)目的編譯過程,本文主要介紹了CMake自動(dòng)管理C/C++項(xiàng)目的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2025-02-02
新版本Qt Creator安裝配置的實(shí)現(xiàn)步驟
本文詳細(xì)介紹了如何在Windows11環(huán)境下,使用Qt5.14.2和VS2017安裝并配置最新版本的QtCreator10.0.2,文中通過圖文示例介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-07-07
C/C++程序開發(fā)中實(shí)現(xiàn)信息隱藏的三種類型
這篇文章主要介紹了C/C++程序開發(fā)中實(shí)現(xiàn)信息隱藏的三種類型的相關(guān)資料,需要的朋友可以參考下2016-02-02

