欢迎光临
我们一直在努力

C/C++内存管理、new/delete操作符深入解析

       

@Shadow

 国服女程序员在线敲代码  撒谎姓倒过来写 ! 快点关注球球了 🎶Ciallo~😎                                                                                 

目录

一、真实内存、虚拟内存

虚拟内存布局图:

各区域功能介绍:

题目练习

二、C++中的内存管理方式

new/delete操作符的使用

内置类型

自定义类型

new与delete的实现原理

内置类型

自定义类型

(1).new的原理

(2).delete的原理

(3).new T[N]的原理

(4).delete[ ]的原理

new与new[ ]内部函数调用导图(复习重点!)

抛异常

三、定位new表达式(placement-new)

四、malloc/free和new/delete的区别


一、真实内存、虚拟内存

概念说明
物理内存 实际的RAM硬件,容量有限(如8GB、16GB)
虚拟内存 操作系统为每个进程提供的独立地址空间,通过MMU映射到物理内存

虚拟内存布局图:

各区域功能介绍:

栈:也叫堆栈–非静态局部变量/函数参数/返回值等等,栈是向下增长的。 堆:用于程序运行时的动态内存分配,堆是可以向上增长的。 数据段:存储全局数据和静态数据。 代码段:可执行代码/只读常量。

题目练习

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);
}

选项
:
A
.

B
.

C
.
数据段
(
静态区
)
D
.
代码段
(
常量区
)

  • globalVar在哪里?____
  • staticGlobalVar在哪里?____
  • staticVar在哪里?____
  • localVar在哪里?____
  • num1 在哪里?____
  • char2在哪里?____
  • *char2在哪里?___
  • pChar3在哪里?____
  • *pChar3在哪里?____
  • ptr1在哪里?____
  • *ptr1在哪里?____         
  •                                                                                                                                                          答案: 1.C2.C3.C4.A5.A7.A8.A9.A10.D11.A12.B

    二、C++中的内存管理方式

    new/delete操作符的使用

    当new/delete对单个元素申请时,new的功能类似于malloc,delete的功能类似于free。二者搭配使用。 但在进行连续空间的申请时使用new [ ] 与 delete [ ] 。

    注意:例如当使用new int[a]{b};进行初始化时 若b<a那么其余元素自动初始化为0。

    具体实现如下:

    内置类型

    int main()
    {
    //内置类型
    //未初始化
    int* p1 = new int; //单个申请空间
    int* pp1 = new int[5];//多组申请 使用"[ ]"
    //初始化
    int* p2 = new int(2); //单组初始化
    int* pp2 = new int[5] {1, 2, 3, 4, 5};//多组初始化

    //销毁
    delete p1;
    delete p2;
    delete[] pp1; //多组销毁 delete[]
    delete[] pp2;

    return 0;
    }

    自定义类型

    class A
    {
    public:
    A(int a = 1, int b = 2)
    :_a(a)
    ,_b(b)
    {
    }
    private:
    int _a ;
    int _b ;
    };

    int main()
    {
    //自定义类型 一定初始化->一定具有构造函数
    A* p1 = new A; //未初始化
    //初始化
    A* p2 = new A(1,2);
    A* p3 = new A(1);
    A* p4 = new A(); //匿名对象

    //多组申请并初始化
    A aa1;
    A aa2;
    A* paa = new A[2]{ aa1,aa2 };

    return 0;
    }

    new与delete的实现原理

    内置类型

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

    自定义类型

    (1).new的原理
    • 调用operator new全局函数申请空间。
    • 调用构造函数,完成对对象的构造。
    (2).delete的原理
    • 调用operator delete全局函数释放对象的空间。
    • 调用析构函数,完成对象的清理。
    (3).new T[N]的原理
    • 调用operator new[ ]全局函数。(1次)  (operator new[ ]与operator new一致)
    • 执行构造函数N次申请。
    (4).delete[ ]的原理
    • 调用operator delete[ ]全局函数。(1次)
    • 执行析构函数N次释放。

    new与new[ ]内部函数调用导图(复习重点!)

    抛异常

    定义:是C++中的一个错误处理机制,指程序在遇到无法正常处理的情况时,抛出一个“异常”将控制权转移给能够处理这个错误的代码。 例如:程序中常设计代码如下(捕获抛异常)

    int main()
    {
    try
    {
    int flag = 1;
    while (1)
    {
    int* p1 = new int[1024 * 1024]; //1MB
    cout << flag << endl;
    ++flag;
    }
    }
    catch (const exception& e)
    {
    cout << e.what() << endl;
    }
    }

    三、定位new表达式(placement-new)

    功能:处理极少情景下的初始化问题

    定位new表达式是在已分配的空间中调用构造函数来初始化一个对象。 构成:1.new(place_ptr)type或者2.new(place_ptr)type(initializer-list)                          指针     类型                                             初始化列表 其中"1.":new(place_ptr)type仅支持自定义类型的初始化—仅适用于无参/全缺省构造函数的自动调用。

    int main()
    {
    //(1)与(2)几乎相同
    //(1)
    A* p1 = new A(1);
    delete p1;

    //(2)

    A* p1 = (A*)operator new(sizeof(A)); // 申请空间 //A*强转
    new(p1)A(1); // 初始化

    //~A();
    p1->~A();
    //operator delete p1;
    operator delete (p1);
    }

    四、malloc/free和new/delete的区别

  • malloc/free是函数,new/delete是操作符。
  • malloc申请后无法初始化,new申请空间后可以初始化。
  • malloc申请空间时需要手动计算所需空间的大小而new不需要只需跟上类型即可、如果是多个对象在[ ]之内指定对象个数即可。
  • malloc的返回值类型是void* 需要强转,new不需要,malloc需要检测是否申请失败(NULL),new需要捕获异常。
  • 申请自定义类型对象时malloc/free只会开辟空间,不会调用构造函数。
  • 赞(0)
    未经允许不得转载:171主机测评 » C/C++内存管理、new/delete操作符深入解析
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址