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++有着自己独立动态内存开辟的方法:
主要通过new
和delete
操作符来实现。new
操作符用于分配单个对象或数组,而delete
和delete[]
分别用于释放这些对象或数组所占用的内存.
下面是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 new
和placement new
两种替代机制。operator new
是new
操作符内部使用的函数,可以被重载以提供自定义的内存分配策略。而placement new
是一种特殊的new
表达式,它允许在已分配的内存上构造对象,而不是分配新的内存。
//用法
new(place_address)type
应用场景:
池化技术:
化技术在C++编程中通常指的是预先分配一定数量的资源(如内存、线程等)并存储在一个“池”中,以便在程序运行时可以快速地从中获取和返回资源,而不是每次都进行昂贵的动态分配和释放操作。
这个就是进行已有空间进行对象实例化
六、C语言和C++内存分配的区别
区别malloc
free
new
delete
malloc
和free
是函数,而new
和delete
是操作符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
在释放空间前会调用析构函数完成空间中资源的清理
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。