【C++内存管理】
内存管理
- 前言
- 1.C语言的动态内存管理方式:
- 1.1malloc
- 1.2calloc
- 1.3realloc
- 1.4free
- 2.C++的内存管理方式
- 2.1new/delete操作内置类型
- 2.1(1)new
- 2.1(2)delete
- 2.2 new和delete操作自定义类型
- 3.operator new与operator delete函数
- 4.7. malloc/free和new/delete的区别
前言
我们编写的程序中所使用的对象都有着严格定义的生存期,全局对象在程序启动时分配,在程序结束时销毁。对于局部自动对象,当我们进入其定义所在的程序块时被创建,在离开块时销毁。局部static对象在第一次使用前分配,在程序结束时销毁。
除了自动和static对象外,C++还支持动态分配对象,动态分配的对象的生命周期与它们在哪里创建是无关的,只有当显示地被释放时,这些对象才会销毁。
除了静态内存和栈内存,每个程序还拥有一个内存池。这部分内存被称作自由空间或者堆。程序用堆来存储动态分配的对象,当动态对象不再使用时,我们的代码必须显示地销毁它们。
1.C语言的动态内存管理方式:
1.1malloc
void* malloc (size_t size);
函数向内存申请一块连可用的空间,并返回指向这个空间的指针。
1.2calloc
void* calloc (size_t num, size_t size);
函数的功能是为 num 个大小为 size 的元素开辟⼀块空间,并且把空间的每个字节初始化为0。
1.3realloc
void* realloc (void* ptr, size_t size);
realloc函数就可以做到对动态开辟内存大小的调整。
1.4free
void free (void* ptr);
C语言提供了另外⼀个函数free,专门是用来做动态内存的释放和回收的。
2.C++的内存管理方式
2.1new/delete操作内置类型
C++语言定义了两个运算符来分配和释放动态内存。运算符new分配内存,delete释放new分配的内存。
2.1(1)new
在自由空间分配的内存是无名的,因此new无法为其分配对象命名,而是返回一个指向该对象的指针:
int *pi = new int;
此时new表达式在自由空间构造一个int型对象,并返回指向该对象的指针。
int* pi = new int(10);
此时pi指向的对象值为10。
int* pi = new int[10];
动态申请10个int类型的空间。
2.1(2)delete
为了防止内存耗尽,在动态内存使用完毕后,必须将其归还给系统,我们通过delete表达式将动态内存归还给系统。delete表达式接受一个指针,指向我们想要释放的对象。
delete ptr1;
delete ptr2;
delete[] ptr3;
2.2 new和delete操作自定义类型
class A
{
public:
A(int a = 0)
: _a(a)
{
cout << "A():" << this << endl;
}
~A()
{
cout << "~A():" << this << endl;
}
private:
int _a;
};
int main()
{
A* p1 = (A*)malloc(sizeof(A));
new(p1)A;
p1->~A();
free(p1);
A* p2 = (A*)operator new(sizeof(A));
new(p2)A(10);
p2->~A();
operator delete(p2);
return 0;
}
3.operator new与operator delete函数
new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。
4.7. malloc/free和new/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在释放空间前会调用析构函数完成空间中资源的清理释放。