• lesson4-C++内存管理


    个人主页:Lei宝啊 

    愿所有美好如期而遇


    目录

    C/C++内存分布

    C语言中动态内存管理方式

    C++中动态内存管理

    operator new与operator delete函数

    new和delete的实现原理

    定位new表达式(placement-new)

    常见面试题


    C/C++内存分布

    我们先来看一段代码:

    1. int globalVar = 1;
    2. static int staticGlobalVar = 1;
    3. void Test()
    4. {
    5. static int staticVar = 1;
    6. int localVar = 1;
    7. int num1[10] = { 1, 2, 3, 4 };
    8. char char2[] = "abcd";
    9. const char* pChar3 = "abcd";
    10. int* ptr1 = (int*)malloc(sizeof(int) * 4);
    11. int* ptr2 = (int*)calloc(4, sizeof(int));
    12. int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
    13. free(ptr1);
    14. free(ptr3);
    15. }

    第一组问题:

    选项 : A .   B .   C . 数据段 ( 静态区 )   D . 代码段 ( 常量区 )   
    问题:以下变量存储在哪里?
    • globalVar
    • staticGlobalVar
    • staticVar
    • localVar
    • num1
    第二段代码:
    1. void Test()
    2. {
    3. char char2[] = "abcd";
    4. const char* pChar3 = "abcd";
    5. int* ptr1 = (int*)malloc(sizeof(int) * 4);
    6. int* ptr2 = (int*)calloc(4, sizeof(int));
    7. int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
    8. free(ptr1);
    9. free(ptr3);
    10. }
    第二组问题:
    选项 : A .   B .   C . 数据段 ( 静态区 )   D . 代码段 ( 常量区 )   
    问题:以下变量存储在哪里?
    •    char2      *char2
    • pChar3      *pChar
    •       ptr1      *ptr1
    第三组问题:
    •    sizeof(num1)
    •    sizeof(char2)        strlen(char2
    • sizeof(pChar3)        strlen(pChar3)
    •       sizeof(ptr1)

    C语言中动态内存管理方式

    malloc/calloc/realloc/free

    C++中动态内存管理

    C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因 此C++又提出了自己的内存管理方式:通过newdelete操作符进行动态内存管理

    new/delete操作内置类型

    new delete 操作自定义类型

    operator new与operator delete函数

    首先我们要明白operator new和operator delete是函数,而new和delete是操作符,他们直接是有联系,但不是重载关系,只是祖师爷起名字这么起。

    operator new函数里调用了malloc函数,也就是说其实可以将他看做是malloc函数的封装,但是不同的是,malloc函数申请空间失败后返回NULL,而operator new函数里实现了判断malloc申请空间失败就抛出异常。

    operator delete函数里也就是调用了free函数,这个函数主要是为了和operator new函数对称匹配。

    new和delete的实现原理

    对内置类型来说

    new操作符底层只调用operator new函数,因为内置类型不需要构造函数和析构函数,所以new也不会调用构造函数

    delete操作符只调用operator delete函数,同理,他也不会调用析构函数。

    对自定义类型来说

    new操作符的底层原理是先调用operator new函数,然后调用构造函数

    delete操作符底层原理是先调用析构函数,然后调用operator delete函数

    1. class Stack
    2. {
    3. public:
    4. Stack(int capacity = 4)
    5. :_capacity(capacity)
    6. ,_top(0)
    7. {
    8. _a = new int[capacity];
    9. _top++;
    10. cout << "构造" << endl;
    11. }
    12. ~Stack()
    13. {
    14. delete[] _a;
    15. _a = nullptr;
    16. _top = _capacity = 0;
    17. cout << "析构" << endl;
    18. }
    19. private:
    20. int* _a;
    21. int _top;
    22. int _capacity;
    23. };
    24. int main()
    25. {
    26. Stack* st = new Stack;
    27. delete st;
    28. return 0;
    29. }

    我们可以查看一下汇编代码来理解。

    1. int main()
    2. {
    3. Stack* st2 = new Stack[3];
    4. delete[] st2;
    5. return 0;
    6. }

    实际上三个对象的空间是一次性全部申请好,然后每个对象都调用构造函数。

    析构的时候我们明明没有给delete[]传大小,他是怎么知道要析构三次的呢?

    我们调试看一下内存

    operator new[]本质上还是调用operator new函数

    operator delete[]里面调用的是operater delete 

    定位new表达式(placement-new)

    定位new是在已申请的原始内存空间中掉用一个构造函数初始化一个对象。

    这个我们现阶段用不上,毕竟直接创建对象自动调用进行初始化多好,总不能malloc自定义类型的对象,然后使用定位new吧,就像这样:

    哪个更好一目了然,我们的定位new真正用途是在内存池那里才会展现。

    常见面试题

    7.1 malloc/free和new/delete的区别
    相同点:
    都需要在堆上申请空间,并且都需要手动释放。
    不同点:
    • malloc和free是函数,而new和delete是操作符
    • malloc开辟空间需要计算大小,而new只需要加上类型,如果需要开辟空间,只需要在[]里指定大小即可。
    • malloc返回值为void*类型,使用时需要强制转换,而new不需要。
    • malloc开辟内存空间失败返回NULL,而new则是抛出异常。
    • malloc开辟的内存空间是原始的,不会初始化,也不能初始化,而new开辟的内存空间可以手动初始化,如果是自定义类型,还会自动去调用他的构造函数;而delete在释放内存空间时会先去调用自定义类型对象的析构函数,free不会。
    7.2 内存泄漏
    内存泄漏就是因为疏忽或者其他原因未能释放已经不再使用的内存空间,失去了对该断内存的控制,最终导致内存出现浪费。
    长期运行的程序出现内存泄漏危害很大,最终会导致响应越来越慢,最终卡死。
  • 相关阅读:
    如何用Python快速生成SQL语句?
    No mapping for GET /swagger-ui.html的解决方法
    JWT -- Json Web token
    2022-08-26 Unity视频播放1——视频介绍
    设备通过国标GB28181协议接入EasyCVR,报错“504 Gateway Time-out”是什么原因?
    【C++】面向对象的理解
    d用户反驳移植到jai的经验
    TypeScript和JavaScript有什么不同?
    tomcat部署、tomcat虚拟主机及tomcat多实例、tomcaty优化
    解密数仓高可用failover流程
  • 原文地址:https://blog.csdn.net/m0_74824254/article/details/134296132