C++:内存管理
目录:
1、C++内存管理
2、C++内存管理方式
3、operator new与operator delete函数
4、new和delete的实现原理
5、定位new表达式(placement-new)
6、malloc/free和new/delete的区别
一、C++内存管理![]()
1、栈:又叫堆栈–局部变量、函数参数、函数返回地址、临时变量,栈是向下增长的。
2. 堆:用于程序运行时动态内存分配,堆是可以上增长的。
3. 数据段:存储全局数据和静态数据。
4. 代码段:可执行的代码/只读常量。
(内核空间和内存映射段了解即可)
高地址 ┌─────────────────┐ │ 栈区 Stack │ ← 局部变量、函数参数、返回地址(向下增长) ├─────────────────┤ │ 堆区 Heap │ ← malloc/new动态内存(向上增长) ├─────────────────┤ │ 全局/静态区 Data │ ← 已初始化全局变量、static变量 │ BSS段 │ ← 未初始化全局变量,默认0├─────────────────┤ │ 常量区 │ ← 字符串常量、const只读常量 ├─────────────────┤ │ 代码区 Text │ ← 函数指令、可执行代码 └─────────────────┘ 低地址二、C++内存管理方式
C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。
3.1 new/delete操作内置类型
voidTest(){// 动态申请一个int类型的空间int*ptr4=newint;// 动态申请一个int类型的空间并初始化为10int*ptr5=newint(10);// 动态申请3个int类型的空间int*ptr6=newint[3];deleteptr4;deleteptr5;delete[]ptr6;}
注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],注意:匹配起来使用。
3.2 new和delete操作自定义类型
#include<iostream>usingnamespacestd;// 自定义类classPerson{public:// 构造函数Person(){cout<<"调用构造函数"<<endl;}// 析构函数~Person(){cout<<"调用析构函数"<<endl;}};intmain(){// 1. new 单个自定义类型Person*p=newPerson;// 释放deletep;p=nullptr;// 置空,防止野指针cout<<"---------"<<endl;// 2. new 自定义类型数组Person*arr=newPerson[3];// 释放数组必须加 []delete[]arr;arr=nullptr;return0;}注意:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会
三、operator new与operator delete函数
operator new / operator delete是全局库函数,不是运算符重载!new 关键字=operator new+调用构造函数delete 关键字= 调用析构函数 +operator delete
(operator new内部调用malloc,operator delete内部调用free)
Person*p=newPerson;// 等价两步:// 1. void* raw = operator new(sizeof(Person)); // 只开空间// 2. new (raw) Person; // 定位new,调用构造operator new:只分配堆内存,不调用构造new 关键字:分配内存 + 构造对象
operator delete:只释放内存,不调用析构delete 关键字:调用析构 + 释放内存
全局默认函数原型
// 分配内存void*operatornew(size_t size);// 释放内存voidoperatordelete(void*ptr);// 数组版本void*operatornew[](size_t size);voidoperatordelete[](void*ptr);四、new和delete的实现原理
new类型 ↓1.申请堆内存(operatornew→ malloc)↓2.调用构造函数 ↓ 返回对象指针delete指针 ↓1.调用析构函数 ↓2.释放内存(operatordelete→ free)new = 内存分配 (malloc) + 构造函数
delete = 析构函数 + 内存释放 (free)
new [] = 分配内存 + N 次构造
delete [] = N 次析构 + 释放内存
malloc/free 不调用构造 / 析构 → 不能用来创建 C++ 对象
new/delete 是 C++ 专为对象设计的
五、定位new表达式(placement-new)
不分配内存,只在已有的内存上调用构造函数
charbuf[100];Person*p=new(buf)Person;// 定位newp->~Person();// 手动析构operatordelete(p);六、malloc/free和new/delete的区别
malloc/free和new/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。
不同的地方是:
1.malloc和free是函数,new和delete是操作符
2.malloc申请的空间不会初始化,new可以初始化
3.malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可, 如果是多个对象,[]中指定对象个数即可
4.malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
5.malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理释放
