C++内存管理(区别C语言)深度对比

chian-ocean 2024-07-21 08:05:04 阅读 54

欢迎来到我的Blog,点击关注哦💕

前言

前面已经介绍了类和对象,对C++面向对象编程已经有了全面认识,接下来要学习对语言学习比较重要的是对内存的管理。

一、内存的分区

代码区:存放程序的机器指令,通常是可共享的,并且通常为只读的,以防止程序意外修改自身的代码。全局/静态存储区:存放全局变量和静态变量,这些变量在程序的整个生命周期内都存在。堆区:用于动态分配内存,程序运行时根据需要通过malloc、calloc、realloc等函数在堆区中分配内存空间。栈区:存放函数的局部变量和函数调用的参数,由编译器自动管理,遵循后进先出的原则。常量区:存放常量数据,如字符串字面量,这些数据在程序运行期间不可修改。代码区:存放程序的二进制代码,是程序执行指令的存储空间。

在这里插入图片描述

二、C语言中的内存管理(参考)

<code>malloc函数用于动态分配指定大小的内存空间,并返回指向该内存的指针。如果分配成功,返回非NULL指针;否则返回NULL。calloc函数除了分配内存外,还会将分配的内存初始化为零。realloc函数用于调整已分配内存的大小,可能会移动内存块以适应新的大小要求。free函数用于释放之前通过动态内存分配函数分配的内存空间

三、C++中的内存管理

C++内存分配

不同于C语言,C++有着自己独立动态内存开辟的方法:

​ 主要通过newdelete操作符来实现new操作符用于分配单个对象或数组,而deletedelete[]分别用于释放这些对象或数组所占用的内存.

下面是new和delete应用的实例:

//动态申请一个int大小空间

int* p0 = new int;

//动态申请一个int大小空间并且初始化为0

int* p1 = new int (0);

//动态申请10个int大小空间

int* p2 = new int[10];

//动态申请10个int大小空间并且初始化为0

int* p3 = new int[10] { 0};

delete p0;

delete p1;

delete[] p2;

delete[] p3;

注意

不要使用delete释放非new开辟的空间不要使用delete释放同一块空间两次如果使用new [ ] 开辟数组进行内存分配,应该使用delete [ ] 来释放如果new对一个实体进行内存分配,应该使用delete(没有方括号)进行释放

四、new 和 delete深度探索

有关operator new 和operator delete

operator new

operator new是一个特殊的操作符,用于动态分配内存。它与new操作符密切相关,但它们在语义上有所区分。

new操作符是一个高级操作符,它不仅分配内存,还自动调用对象的构造函数。

operator new仅负责分配内存,不涉及对象的构造。

operator new可以被重载,以便为特定的类或全局范围提供自定义的内存分配策略

operator new:该函数实际通过``malloc来申请空间,当malloc`申请空间成功时直接返回

申请空间失败, 尝试执行空 间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。

通俗的讲 ,new 不仅仅可以进行空间开辟,针对自定义类型会调用其构造函数,而new也是调用重载(operator new),进行内存的分配,然而 operator new 进行内存分配是通过malloc进行实现的,这正是区别于C语言的其中一点。

关于时间类和汇编语言:

class Date

{

public:

Date(int year = 1,int month = 1,int day = 1)

:_year(year)

,_month(month)

,_day(day)

{ }

~Date()

{

_year = 0;

_month = 0;

_day = 0;

}

private:

int _year = 1;

int _month = 1;

int _day = 1;

};

Date* d1 = new Date;

00007FF62A0D19FC mov ecx,0Ch

00007FF62A0D1A01 call operator new (07FF62A0D103Ch) 。//调用operator new内存分配

00007FF62A0D1A06 mov qword ptr [rbp+108h],rax

00007FF62A0D1A0D cmp qword ptr [rbp+108h],0

00007FF62A0D1A15 je main+5Dh (07FF62A0D1A3Dh)

00007FF62A0D1A17 mov r9d,1

00007FF62A0D1A1D mov r8d,1

00007FF62A0D1A23 mov edx,1

00007FF62A0D1A28 mov rcx,qword ptr [rbp+108h]

00007FF62A0D1A2F call Date::Date (07FF62A0D13D4h) // 调用构造函数

00007FF62A0D1A34 mov qword ptr [rbp+118h],rax

00007FF62A0D1A3B jmp main+68h (07FF62A0D1A48h)

00007FF62A0D1A3D mov qword ptr [rbp+118h],0

00007FF62A0D1A48 mov rax,qword ptr [rbp+118h]

00007FF62A0D1A4F mov qword ptr [rbp+0E8h],rax

00007FF62A0D1A56 mov rax,qword ptr [rbp+0E8h]

00007FF62A0D1A5D mov qword ptr [d1],rax

operator delete

operator delete 是一个全局函数,用于释放之前通过 operator new 分配的内存。它是 new 操作符的逆运算,负责在内存释放时执行必要的清理工作。operator delete 通常在 delete 表达式中被隐式调用,用于释放单个对象或对象数组的内存在空间上执行析构函数,完成对象中资源的清理工作调用operator delete函数释放对象的空间(通过free)

00B72150pushebp已用时间<=1ms

00B72151movebp,esp

00B72153subesp,0cCh

00B72159pushebx

00B7215Apushesi

00B7215Bpushedi

00B7215Cpushecx

00B7215Dleaedi,[ebp-0Ch]

00B72160movecx,3

00B72165moveax,0cccccccch

00B7216Arep stosdword ptr es:[edi]

00B7216Cpopecx

00B7216Dmovdword ptr [this],ecx

00B72170movecx,dword ptr [this]

00B72173callA::~A (0B7154Bh)//调用析构函数

00B72178moveax,dword ptr [ebp+8]

00B7217Bandeax,1

00B7217Eje__call_empty_init_list_helper<A>+0Eh (0

00B72180push4

00B72182moveax,dword ptr [t.ebp15990024

00B72185pusheax

00B72186calloperator delete (0B710AAh)//释放空间

00B7218Baddesp,8

00B7218Emoveax,dword ptr [this]

00B72191popedi

00B72192popesi

小结

new 和delete 调用的时候内部调用的顺序

new 先进行空间的开辟(malloc),在进行对象的实例化delete先进行析构函数的调用,进行资源的销毁,在进行空间的释放(free

五、replacement new

在C++中new操作符通常用于在堆上分配内存并调用对象的构造函数。除了常规的new操作符外,C++还提供了operator newplacement new两种替代机制。operator newnew操作符内部使用的函数,可以被重载以提供自定义的内存分配策略。而placement new是一种特殊的new表达式,它允许在已分配的内存上构造对象,而不是分配新的内存。

//用法

new(place_address)type

应用场景:

池化技术:

化技术在C++编程中通常指的是预先分配一定数量的资源(如内存、线程等)并存储在一个“池”中,以便在程序运行时可以快速地从中获取和返回资源,而不是每次都进行昂贵的动态分配和释放操作。

这个就是进行已有空间进行对象实例化

六、C语言和C++内存分配的区别

区别malloc free new delete

mallocfree是函数,而newdelete是操作符malloc不可以初始化而new可以初始化malloc进行内存分配的时候是手动计算空间的大小,而new后面跟类型,大小在 [ ]中指定malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型malloc申请空间失败是返回NULL,而new申请空间失败是捕获异常申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间 后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理

void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型

5. malloc申请空间失败是返回NULL,而new申请空间失败是捕获异常

6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间 后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。