动态内存管理
在 C++ 中,new
和 delete
操作符用于动态内存管理,它们允许在堆上分配和释放内存。它们的用法如下:
new
操作符
new
用于在堆上分配内存,它返回一个指向所分配内存块的指针。
用法:
-
内置类型:
int* p = new int(5); // 申请一个int类型的内存空间,初始化为5 *p = 10; // 给分配的内存赋值
这里,
new int
会在堆上分配一个int
类型的内存,并返回指向该内存的指针。针对内置类型可以在类型后面接一个括号表示初值如
int* p = new int(5);
。 -
自定义类型(类类型):
class MyClass { public: int value; }; MyClass* p = new MyClass; // 分配一个 MyClass 类型的对象 p->value = 10; // 访问成员变量
对于类类型,
new MyClass
会在堆上分配一个MyClass
类型的对象,并调用构造函数。
delete
操作符
delete
用于释放由 new
分配的内存,避免内存泄漏。
用法:
-
内置类型:
delete p; // 释放 int 类型内存
这里,
delete
会释放之前通过new
分配的内存。 -
自定义类型(类类型):
delete p; // 释放 MyClass 类型对象
delete
会释放new MyClass
所分配的内存,并调用类的析构函数。
总结
内置类型:new
用于分配基本类型的内存,delete
释放它们。
自定义类型:new
分配类类型对象时,会调用构造函数,delete
会调用析构函数。
数组:使用 new[]
和 delete[]
分配和释放数组时,必须匹配。
int* arr = new int[10]; // 分配一个大小为 10 的整数数组
delete[] arr; // 释放数组内存
operator new
函数
operator new
是 C++ 中的内存分配函数,用于在堆上分配内存。它的功能类似于标准库的 malloc
,但是与 new
操作符不同,operator new
返回的是一个原始的指针,而不进行类型的构造。
基本用法:
void* operator new(std::size_t size);
- 参数:
size
是需要分配的字节数。 - 返回值:返回一个指向分配内存的指针,如果内存分配失败,通常会抛出
std::bad_alloc
异常。 - 实现:实际通过
malloc
来申请空间,当malloc
申请空间成功时直接返回,申请空间失败时,抛异常。
operator delete
函数
operator delete
用于释放通过 operator new
分配的内存。它的作用与 delete
操作符类似,但不会调用对象的析构函数(在对象被销毁时,delete
会调用析构函数,而 operator delete
只是简单释放内存)。
基本用法:
void operator delete(void* pointer);
- 参数:
pointer
是指向要释放内存的指针。 - 实现:实际通过
free
来释放空间。
operator new[]
和 operator delete[]
类似于 new[]
和 delete[]
操作符,operator new[]
和 operator delete[]
用于数组的内存分配和释放。
operator new[]
:在堆上分配一块内存来存储一个数组。operator delete[]
:释放通过operator new[]
分配的数组内存。
void* operator new[](std::size_t size);
void operator delete[](void* pointer);
new
和delete
的实现原理
内置类型
new
和malloc
,delete
和free
基本类似,不同的地方是:
malloc
申请失败时会返回NULL
new
申请失败时会抛异常
自定义类型
new
- 调用
operator new
函数申请空间 - 在申请的空间上执行构造函数
- 调用
delete
- 在空间上执行析构函数
- 调用
operator delete
函数释放空间
malloc/free和new/delete的区别
共同点:都是从堆上申请空间,需要手动释放
不同点:
malloc
、free
是函数,new
、delete
是操作符malloc
申请的空间不会初始化,new
可以初始化malloc
申请空间时,需要手动计算空间大小并传递,new
只需在其后跟上空间的类型即可malloc
的返回值为void*
, 在使用时必须强转,new
不需要,因为new
后跟的是空间的类型malloc
申请空间失败时,返回的是NULL
,因此使用时必须判空,new
不需要,但是new
需要捕获异常- 申请自定义类型对象时,
malloc/free
只会开辟空间,不会调用构造函数与析构函数,而new
在申请空间后会调用构造函数完成对象的初始化,delete
在释放空间前会调用析构函数完成空间中资源的清理