• C/C++内存管理相关知识点


    1.内存分布

    C/C++将内存大体上分为四个区域:栈区、堆区、静态区(数据段)、常量区(代码段)。

    栈区:用来存储函数调用时的临时信息的结构,存放为运行时函数分配的局部变量、函数参数、返回数据、返回地址等。

    堆区:程序员自己使用malloc或new自己申请出来存的地方。(动态内存分配)

    静态区: static修饰的数据,全局数据,存放的位置。

    常量区:不会改变的常量,存在这里。


    看下面一段代码,回答问题:

    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    看上面一段代码,请回答如下:

    在这里插入图片描述
    在这里插入图片描述

    2. new/delete关键字

    2.1 操作内置类型

    int main()
    {
    
    	//动态申请一个int 类型的空间
    	int* ptr1 = new int;
    	delete ptr1;			//释放ptr1
    	
    	// 动态申请一个int 类型的空间,并初始化为 5
    	int* ptr2 = new int(5);
    	delete ptr2;		   //释放ptr2
    
    	// 动态申请5个int 类型的空间
    	int* ptr3 = new int[5];
    	delete[] ptr3;         // 释放ptr3,注意怎么new的怎么delete
    
    	 动态申请5个int 类型的空间,并初始化
    	int* ptr4 = new int[5]{ 1,2,3 };
    	delete[] ptr4;		   // 释放ptr4,注意怎么new的怎么delete
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    **注意:new 对应 delete,new [] 对应 delete [] 。**不可用错。

    操作自定义类型

    new 和 delete 除了申请和释放空间外,会自动调用构造函数和析构函数。

    class A
    {
    public:
    	A(int a = 0)
    	{
    		cout << "A()" << endl;
    	}
    	~A()
    	{
    		cout << "~A()" << endl;
    	}
    
    private:
    	int _day;
    	int _year;
    	int _month;
    };
    
    int main()
    {
    	A* p1 = new A(1);  //一次构造
    	delete p1;			//一次析构
    
    	A* p2 = new A[5];  // 五次构造
    	delete[] p2;       //五次析构
    
    	
    
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    3. opeartor new 与 operator delete函数

    newdelete是 用户进行动态内存申请和释放的操作符,operator newoperator delete 是系统提供的全局函数,new在底层调用 operator new 全局函数来申请空间,delete在底层通过 operator delete 全局函数来释放空间。

    其中:
    operator new:该函数实际通过malloc来申请空间,申请成功直接返回;失败时,尝试执行空间不足应对策略,如果用户对该措施设置了,继续申请空间,否则抛异常。

    operator delete:该函数最终是通过free()来释放空间的。


    在这里插入图片描述
    通过该定义也可以看出,free()其实也是一个重命名,真正的函数名是后面的。

    4. new 和 delete 原理

    4.1 内置类型

    如果申请的是内置类型空间,new和malloc,delete和free基本类似,不同的地方是:new和delete申请和释放的是单个元素空间,new[]和delete[]申请和释放的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。

    4.2 自定义类型

    • new的原理
      1.调用operator new 申请空间
      2.在申请的空间上执行构造函数,完成对象的构造。

    • delete 原理
      1.在空间上执行析构函数,完成对象中资源的清理工作
      2.调用operator delete函数释放对象的空间

    • newT[N] 原理
      1.调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请。
      2.在申请的空间上执行N次构造函数

    • delete[] 原理
      1.在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理。
      2.调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间

    如下例子总结:
    在这里插入图片描述

    5.定位new表达式(placement-new)

    定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。

    使用语法:
    new (place_address) type 或者new (place_address) type(initializer-list)
    place_address必须是一个指针,initializer-list是类型的初始化列表。

    
    new(p1)A;    //如果A的构造函数有参数,此处需要传参
    nwe(p2)A(10);  // 初始化参数为10
    
    
    • 1
    • 2
    • 3
    • 4

    6. malloc/free 和 new/delete的区别

    共同点:
    都是从堆上申请空间,并需要手动释放。

    不同点:

    1. malloc和free是函数,new和delete是关键字。
    2. malloc申请的空间不会初始化,new可以调用构造函数完成初始化。
    3. malloc申请空间时,需要手动计算空间大小并传递,new只需在其后面跟上空间的类型即可,如果是多个对象,[]中指定个数即可。
    4. malloc返回值是void*,在使用时必须强转,new不需要,因为new后面跟的是空间类型。
    5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是需要捕获异常。
    6. 申请自定义类型时,malloc/free 只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成对象空间中资源的清理。

    7. 内存泄漏

    相关知识后续会继续补充。。。

  • 相关阅读:
    Prometheus-监控Mysql进阶用法(1)(安装配置)
    线程执行测试效果
    JAVA卓越导师双选系统计算机毕业设计Mybatis+系统+数据库+调试部署
    [Spring] Spring5——IOC 简介(二)
    【此时不应有 \anaconda3\envs\ blenderproc \Library\ssl\cacert.pem】问题已解决
    Python 在问答频道中刷题积累到的小技巧(七)
    微软8月系统更新引发问题:虚拟内存分页文件出现错误
    前端安全分享
    在数据框中如何把变量定义为整数型数据
    【数据结构基础_树】Leetcode 108.将有序数组转换为二叉搜索树
  • 原文地址:https://blog.csdn.net/weixin_45153969/article/details/132909867