
◆博主名称:少司府
欢迎来到少司府的博客☆*: .。. o(≧▽≦)o .。.:*☆
⭐数据结构系列个人专栏:
⭐C++基础个人专栏:
⭐名不显时心不朽,再挑灯火看文章
目录
[一、C/C++ 内存分布](#一、C/C++ 内存分布)
[1.1 例题引入](#1.1 例题引入)
[1.2 内存区域划分](#1.2 内存区域划分)
[2.1 new和delete](#2.1 new和delete)
[2.1.1 对于内置类型](#2.1.1 对于内置类型)
[2.1.2 对于自定义类型](#2.1.2 对于自定义类型)
[2.2 operator new 和 operator delete 函数](#2.2 operator new 和 operator delete 函数)
[3.1 内置类型](#3.1 内置类型)
[3.2 自定义类型](#3.2 自定义类型)
[3.2.1 new的原理](#3.2.1 new的原理)
[3.2.2 delete的原理](#3.2.2 delete的原理)
[3.2.3 new T[N] 和 delete[] 的原理](#3.2.3 new T[N] 和 delete[] 的原理)
[3.3 实际空间结构](#3.3 实际空间结构)
一、C/C++ 内存分布
1.1 例题引入
我们通过一道例题来引入讲解C/C++的内存分布:
cpp
int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
static int staticVar = 1;
int localVar = 1;
int num1[10] = { 1, 2, 3, 4 };
char char2[] = "abcd";
const char* pChar3 = "abcd";
int* ptr1 = (int*)malloc(sizeof(int) * 4);
int* ptr2 = (int*)calloc(4, sizeof(int));
int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
free(ptr1);
free(ptr3);
}

如图,易知:
1)、glovalVar 是全局变量 ,存在静态区
2)、staticGlobalVar 是全局静态变量,存在静态区
3)、staticVar 是局部静态变量,存在静态区
4)、localVar 和 num1 存在函数开辟的栈帧空间里面
5)、char2 是栈上定义的数组,数组名及元素 *char 都存在栈上
6)、pchar3 在栈上定义,存在栈上;常量字符串存在常量区
7)、malloc、calloc、realloc 开辟的空间在堆上
1.2 内存区域划分

如图,需要注意的是:
在32位下,虚拟空间是4G,指针是4个字节,(指针在内存中是编号,00000000 到 FFFFFFFF 刚好是2^32 个编号,也就是4G),堆的空间大概1.8G左右,栈大概8M。
在64位下,虚拟空间是2^32 * 4G ,指针是8个字节。
|--------------|----------------------------------------------------------|
| 栈 | 又叫堆栈,存放非静态局部变量/函数参数/返回值等等,栈是向下增长的。 |
| 内存映射段 | 高效的I/O映射方式,用于装载一个共享的动态内存库 。用户可使用系统接口创建共享共享内存,做进程间通信。 |
| 堆 | 用于程序运行时动态内存分配,堆是可以上增长的。 |
| 数据段(静态区) | 存储全局数据和静态数据。 |
| 代码段(常量区) | 可执行的代码/只读常量。 |
二、C++管理内存方式
2.1 new和delete
C++中使用new来申请空间,delete来释放空间。
2.1.1 对于内置类型

如图,delete删除的时候要和申请出来的类型一一对应。
2.1.2 对于自定义类型
cpp
A* p1=new A(1,2); // new对于自定义类型,会自动调用构造函数,申请对象+初始化
A* p2=new A[3]; // 调用3次构造
A* p3=new A[3]{A{1,1},A{2,2},A{3,3}};
A* p4=new A[3]{{1,1},{2,2},{3,3}};
delete p1; // delete对于自定义类型,会自动调用析构函数
delete[] p2;
delete[] p3;
delete[] p4;
如图,对于自定义类型,new是 malloc+构造,delete是 析构+free
2.2 operator new 和 operator delete 函数
new 和 delete 是用户进行动态申请和释放的操作符,operator new 和 operator delete 是系统提供的全局函数,new在底层调用operator new 来申请空间,delete在底层调用operator delete来释放空间。
而operator new 的底层是malloc,operator delete 的底层是free。
三、new和delete的实现原理
3.1 内置类型
对于内置类型的空间,malloc/free 和 new/delete 基本类似区别在于:new 在申请空间失败会抛异常,malloc会返回NULL。

3.2 自定义类型
3.2.1 new的原理
1)、调用operator new 函数申请空间,申请失败就抛异常(operator new 调 malloc)
2)、在申请的空间上执行构造函数,完成对对象的构造
3.2.2 delete的原理
1)、在空间上执行析构函数,完成对象中资源的清理
2)、调用operator delete函数释放对象的空间
3.2.3 new T[N] 和 delete[] 的原理
同理,调N次构造或者析构
3.3 实际空间结构
cpp
B* p2=new B[10]; // 假设A、B均为8字节,且B没有写析构
A* p3=new A[10];
delete p2;
delete p3; // error -> delete[] p3;
// 释放位置不对

四、定位new表达式
定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
cpp
A* p2=(A*)operator new(sizeof(A));
new(p2)A(10); // placement new,定位new,对已开辟的空间显示调用构造函数
p2->~A(); // 显示调用析构
operator delete(p2);
使用场景:
定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如 果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。
本期的分享就到这里,如果觉得博主的文章比较对胃口的话,可以点一个小小的关注~
您的三连是我持续更新的动力~