C++-- 内存管理

计算机的核心资源有CPU/GPU,内存,磁盘,我们本文讲解的是内存分布

一.内存分布

首先我们用之前的知识先判断各个变量以及常量所处哪个区

cpp 复制代码
int globalVar = 1;   //全局变量  在数据段(已经初始化的读写区)

static int staticGlobalVar = 1; //静态全局变量。数据段

void Test()
{
static int staticVar = 1;  //静态局部变量,数据段

int localVar = 1;  //局部变量,栈

int num1[10] = { 1, 2, 3, 4 };num1 局部数组,存放到栈

char char2[] = "abcd"; //char2 局部数组,栈   ;   abcd本身是字符串常量,在常量区

const char* pChar3 = "abcd";  //pchar3局部指针变量,栈

int* ptr1 = (int*)malloc(sizeof(int) * 4); //ptr1这指针变量在栈  ;  指向的内存在堆
int* ptr2 = (int*)calloc(4, sizeof(int));  //同上
int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4); //同上,可能在新块,因为有原地扩容异地扩容
free(ptr1);
free(ptr3);
}
cpp 复制代码
从低地址到高地址

1.代码段
// 所有可执行代码在这里

int main() {
    return 0;
}

void function() {
    // 函数体二进制代码
}


2。常量区
const char* string_literal = "Hello World";  // "Hello World"常量字符串
const int const_global = 100;               // 常量全局变量在RODATA
#define MAX_SIZE 1000                       // 宏定义,预处理替换

3.数据段 -- 已经初始化的全局变量
int global_initialized = 42;                // 数据段
static int static_global = 123;             // 数据段
char global_str[] = "global";               // 数据段(可修改的全局数组)

4.BSS段 --未初始化的全局变量
int global_uninitialized;                   // BSS段,默认初始化为0
static int static_uninitialized;            // BSS段
int global_array[1000];                     // 大数组在BSS段

5.堆区 --动态内存分配        //这里的指针都是局部变量,在栈,分配的内存在堆
void heap_example() {
    int* ptr1 = (int*)malloc(100 * sizeof(int));     // 堆区
    int* ptr2 = new int[50];                         // C++堆区
    char* str = (char*)calloc(256, sizeof(char));    // 堆区
    
    free(ptr1);
    delete[] ptr2;
    free(str);
}

6,栈  --局部变量,函数调用
void stack_example(int param) {           // 参数param在栈区
    int local_var = 10;                   // 局部变量在栈区
    char local_str[] = "stack";           // 局部数组在栈区
    int local_array[100];                 // 局部数组在栈区
    
    if (true) {
        int block_scope_var = 20;         // 块作用域变量在栈区
    }
    
    // 函数调用信息在栈区
    recursive_function(5);
}
内存区域 存储内容 生命周期 读写权限
代码段 程序代码 程序运行期 只读
RODATA 字符串常量、const全局变量 程序运行期 只读
数据段 已初始化全局/静态变量 程序运行期 读写
BSS段 未初始化全局/静态变量 程序运行期 读写
堆区 动态分配内存 手动管理 读写
栈区 局部变量、函数参数 函数作用域 读写

二.C++内存管理

C++中引入了构造和析构函数,C的内存管理体系就不再那么适合了,因为处理起来考虑较多,所以C++就有了操作符new和delete进行 动态内存管理

cpp 复制代码
void text()
{
    int* ptr1 = new int;
    int* ptr2 = new int[10];  //申请十个int类型的空间
    int* ptr3 = new int(4);   //初始化这个申请的整型
    int* ptr4 = new itn[2]{3}; //初始化申请的两个整型,首个初始化为3,没写的默认0

    delete ptr1;
    delete[] ptr2;
    delete ptr3;
    delete[] ptr4;
}

1.new 和 delete和malloc / delete区别最大的是其对自定义类型会自动调用其构造函数和析构函数

2.malloc内存分配失败会判断后返回,new失败会默认抛异常std::bad_alloc,当然也可也模仿malloc对其进行返回nullptr的判断

3.不可混用

三.operator new 和 operator delete函数

作用:new在底层调用operator new全局函数来申请空间。delete在底层通过operator delete全局函数来释放空间

结论:实际上operator就是用malloc来分配内存,成功则返回。否则执行用户提供的空间不足应对措施,如果用户提供该措施 就继续申请,否则就抛异常。operator delete最终是通过free****来释放空间的

四.new和delete原理

内置类型:

如果申请内置类型内存,则new和malloc,delete和free基本类似,

new/delete是申请释放单个元素空间,new[]和delete[]是申请释放连续空间。

new申请失败会抛异常,malloc返回NULL

自定义类型:

  • new 使用operator new申请指定类型的一个空间。后调用构造函数
  • delete 先析构,释放资源 。然后用operator delete释放对象空间
  • new[ ] 使用operator new[ ]函数申请n个空间,后调用n次构造函数
  • delete[ ] 析构n次,释放资源,然后调用operator delete[ ]释放对象空间
  1. malloc和free是函数,new和delete是操作符
  2. malloc申请的空间不会初始化,new可以初始化

五.定位new

手动实现new,用上面的底层调用operator new和operator delete机制

cpp 复制代码
A* p1 = new A(1);
delete p1;
//这两行相当于下面几行

A* p2 = (A*)operator new(sizeof(A)); //p1现在指向的只不过是与A对象相同大小的一段空间,还不能算是一个对象,因为构造函数没有执行
new(p2)A(1);

//构造函数不能直接调用
//析构函数可以直接调用

p2->~A();
operator delete(p2);

这个会利用于池化技术。就是等于说可以声明一个获取内存的池子,要是不这样分布实现,直接调用new就会直接从系统堆上申请,效率不高,然后这样的话就可以手动指定获取内存的地方

具体效率高在哪,我们后期linux系统编程的线程池等等会介绍

相关推荐
2301_795167202 小时前
玩转Rust高级应用 如何避免对空指针做“解引用”操作,在C/C++ 里面就是未定义行为
c语言·c++·rust
智驱力人工智能4 小时前
基于视觉分析的人脸联动使用手机检测系统 智能安全管理新突破 人脸与手机行为联动检测 多模态融合人脸与手机行为分析模型
算法·安全·目标检测·计算机视觉·智能手机·视觉检测·边缘计算
2301_764441335 小时前
水星热演化核幔耦合数值模拟
python·算法·数学建模
循环过三天5 小时前
3.4、Python-集合
开发语言·笔记·python·学习·算法
priority_key7 小时前
排序算法:堆排序、快速排序、归并排序
java·后端·算法·排序算法·归并排序·堆排序·快速排序
不染尘.7 小时前
2025_11_7_刷题
开发语言·c++·vscode·算法
似水এ᭄往昔8 小时前
【C++】--stack和queue
开发语言·c++
仰望—星空8 小时前
MiniEngine学习笔记 : CommandListManager
c++·windows·笔记·学习·cg·direct3d
来荔枝一大筐8 小时前
力扣 寻找两个正序数组的中位数
算法
算法与编程之美9 小时前
理解Java finalize函数
java·开发语言·jvm·算法