自学内容网 自学内容网

c/c++内存管理(详解) + new与delete的用法及底层

1:c/c++内存分布情况

        1.1:c/c++内存的分布图

        1.2:每个区域的用途及不同类型变量存储在那个区

        1.3:例题讲解

2:c++动态内存管理方式(new  delete)

        2.1:new的语法

        2.2:delete的语法

3:operator new函数与operator delete函数

4:new与delete的实现原理

5:定位new表达式初识

6:malloc/free与new与delete的区别

7:delete与delete[]的区别


声明:图片均来自网上

1:c/c++内存分布情况

1.1c/c++内存的分布图

        如下图:

        如上图所示:我们c/c++语言内存分布的区域有:内核空间,栈区,内存映射段,堆区,数据段(静态区),代码段(常量区),由于对一些区域不是很了解,所以我们在这里只会挑选一些在语言中经常使用的区域进行讲解:栈区,堆区,数据段(静态区),代码段(常量区)

        在了解上面每个区域的作用前我们需要知道为什么有不同的区域划分呢?

        在我们的生活中我们知道,在我们家乡,政府将每个地方分成不同的区域,而这些区域是用来发展不同的经济产业,满足不同的需求。

        就如家乡的区域划分一样,我们的c/c++语言划分区域是因为我们不同的数据,有不同的存储需求,而每个区域就能满足这些数据的需求。

    1.2:每个区域的用途及不同类型变量存储在那个区

        栈区:临时用的变量,函数栈桢,局部变量。

        堆区:我们向系统动态申请空间的地方,各种数据结构。

        数据段(静态区):全局变量,static定义的变量。

        代码段:各种只读常量,指令。


1.3:例题讲解

        答案:CCCAA        AAADAB

下面我们通过内存分布图来完成上面的习题。

        解析如上图。重点是我们需要理解每句话的内容,然后根据内容找到相对应的空间。

        栈是向下增长的地址变小,堆是想上增长的地址变大,堆栈相对而生。


2:new与delete的用法

        我们通过下面代码来学习new与delete的语法:

        

// new + 类型  并未初始化 申请一个空间
int* p1 = new int;//开辟一个空间的用法

//申请多块空间  new + 类型[]
int* p2 = new int[10];//开辟10个整形空间 并未初始化

//开辟空间并初始化
int* p3 = new int(1);
int* p4 = new int[10]{ 1,2,3,4 };//初始化部分其它的空间全为0

return 0;

new+类型开辟空间    new+类型[n]:开辟n个空间   对于一个空间的初始化用(),对于一堆空间的初始化为{}符号,new与malloc一样默认初始化为随机值。

以上为vs调试下的开辟空间。

总结:用new创建的对象,我们就用delete对象   new[] 对象------delete[] 对象。对于内置类型的对象申请/释放空间 与malloc/free除了用法上,没有区别。


3:operator new函数与operator delete函数

       new和delete是用户申请/释放空间的操作符 operator new与operator delete则是由系统提供的全局函数。  new的底层调用了 operator new函数申请空间,delete底层调用了operator delete函数释放空间。

       下图是 operator new函数的实现,我们可以知道operator new 底层调用了 malloc函数与使用了面向对象处理错误的方法

对比的来说operator delete的底层肯定调用了free函数来释放空间。

总结:operator new  =malloc+抛异常。operator delete =free


4:new和delete的实现原理

        对于内置类型申请/释放空间   new  = operator new    delete =operator delete,而他们本质上分别调用了 malloc与free函数,也就是说  对于内置类型成员  new =malloc  delete =free,只是他们在用法上面不同而已。

        而对于自定义类型对象来说:new = operator new+ 调用构造函数。delete =operator delete+调用析沟函数。

我们用vs代码来测试我们说的内容:

class Stack
{
public:
Stack(int capacity = 4)
{
_a = new int[capacity];
cout << "Stack(int capacity = 4)" << endl;
_top = 0;
_capacity = 0;
}

~Stack()
{
cout << "~Stack()" << endl;
delete _a;
}
private:
int* _a;
int _top;
int _capacity;

};

上面是我们简写的栈

我们下面用它创建1个类对象

在这个案列中我们就可以发现,对于自定义类型对象使用new与delete,new底层实现是 构造+operator new(开空间), delete=operator delete +调用析沟


我们来仔细分析这个代码是如何申请内存的,如何两次使用new的。


5:定位new表达式

        在我们学习定位new的时候,我们先来回忆之前我们学过的知识点,构造函数只有在定义对象的时候才会被调用。

        假如我们先给对应的类对象开辟空间,那么我们之后如何初始化呢?代码如下

int main()
{
Stack * p = (Stack* )malloc(sizeof(Stack));

return 0;
}

   在这种情况下,我们并没有调用构造函数,那么我们该如何调用构造函数呢?

我们使用p->Stack(),是不行的,因为构造函数只有在定义对象的时候才能被调用。

这种时候如果我们想要调用构造函数,我们就必须使用定位new的知识点了。

定位new语法:new(申请空间address)构造函数调用方式

如下:new(p)Stack().

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

以后会补上定位new的使用场景。


6:malloc/free与new与delete的区别

1:new与delete是操作符,malloc与free是函数调用的时候需要包含相应的头文件。

2:malloc申请的空间不会初始化,new可以进行初始化。

3:malloc申请空间需要手动的计算开空间的大小,new 开辟对象类型[n],n表示要开辟多少个n对象.

4:malloc的返回值为(void*)使用的时候需要强转,new没有返回值。

5:malloc申请空间的时候失败返回NULL,而new失败我们只需要对他进行捕获异常即可。

6:申请自定义类型空间的时候,malloc/free只会申请/释放空间,而new=开空间+调用对应的构造函数,free=释放空间+调用析沟函数

7:delete与delete[]的区别

        首先我们要知道在用法上:delete-----new,delete[]------new[],这两个用法上最好是这样一一对应的,不然有时候程序就会崩溃。

其实当我们使用delete[]的时候,我们的编译器会多开辟一个整形大小的空间,这个空间用来记录我们之前开了多少个对象。

我们调用delete[]的时候,也会将这个多开辟空间给释放掉。

而如果没加[],就直接从p开始释放空间。

总结:new---delete  new [] ---delete[].

本章知识点分享完毕,感谢大家的耐心观看。


原文地址:https://blog.csdn.net/2201_75964502/article/details/142440596

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!