自学内容网 自学内容网

C++内存管理

要学习C++的内存管理,首先我们需要回顾一下C语言的内存管理,

1.回顾C语言的内存管理

我们现在需要理解C语言的四块内存区域。

栈:        又叫堆栈-非静态局部变量/函数参数/返回值等等,栈是向下增长的。

堆:        用于程序运行时动态内存的分配,堆是可以向上增长的。

数据段:存储全局数据和静态数据 

代码段:可执行的代码/只读常量 

让我们看看什么样的数据存储在这些内存空间中

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

C语言中动态内存的管理方式需要用到几个函数:malloc  /   calloc   /   realloc    /     free

1.malloc 

 malloc的用法一般形式为:类型名*指针名   =  (类型名*)malloc(需要开辟空间的字节大小)

int*ptr=(int*)malloc(sizeof(int));

2.calloc 

 

 calloc的用法一般形式为:类型名*指针名=(类型名*)calloc(所要开辟类型空间个数,每个类型空间的大小)

int* ptr=(int*)calloc(6,sizeof(int));

3.realloc 

 

realloc的用法一般形式为: 类型名*指针名2=(类型名*)realloc(指针1,所需字节个数空间大小)

 realloc一般是用来扩大一个已经存在的动态内存空间的

 

 如上图,我们要扩大指针1指向的动态内存空间,那我们就给realloc指向这个空间的指针和要扩大至想要空间的大小,再用指针2去接收这块空间的地址。

特殊情况:当扩大的空间和已经使用的空间重叠时,操作系统会重新再找一块空间来复制这块空间的数据

 

4.free

free函数用于动态内存空间的释放,因为我们开辟空间都是在堆中开辟,如果我们一直开辟空间,那么迟早堆里面的空间会被使用完,所以我们需要使用free函数来把这块空间释放给操作系统

 free用法一般形式free(指向空间的指针名)

int* ptr= (int*)malloc(sizeof(int) * 6);
free(ptr);

当我们在堆中开辟了一块空间,之后我们不使用它了,我们一定要释放,不然会造成内存泄漏。 

3.C++内存管理方式

C语言中的内存管理方式也可以放到C++中使用,但有些时候可能不太适合而且很麻烦,所以C++提供了自己的内存管理方式,通过两个操作符进行管理:new和delete。

1.new

#include<iostream>
using namespace std;
int main()
{
int* ptr2 = new int;

int* ptr1 = new int(10);

int* ptr = new int[5] {0, 1, 2};

}

上述new是和malloc类似,也是开辟空间 

第一个是开辟一个存放int类型数据的空间并且用ptr2指向这个空间

第二个是开辟一个存放int类型数据的空间,并且将这int类型的数据初始化为10用ptr1指向 

第三个是开辟一个大小为5的数组,并且数组前三个用{}里的数据对应初始化,其它没有初始化的数据都为0 

2.delete 

那么上面开辟了空间就要释放,C++提供了一个操作符delete来释放new出来的空间

#include<iostream>
using namespace std;
int main()
{
int* ptr2 = new int;

int* ptr1 = new int(10);

int* ptr = new int[5] {0, 1, 2};

delete ptr2;

delete ptr1;
 
delete[]ptr;
}

上述就是释放空间的格式,需要注意数组的初始化有所不同,要在指针和delete中间加[ ] 

 3.new和malloc的区别

对于内置类型的数据来说,malloc和new的差别不大,new和malloc的区别主要时在用于自定义类型有所差别。

我们看下面代码

#include<iostream>
using namespace std;
class A
{
public:
A()
{
cout << "A()" << endl;
}
~A()
{
cout << "~A()" << endl;
}
private:
int aa;
};
int main()
{
A* ptr1 = new A;
}

当new用于自定义类型时对调用自定义类型的构造函数,

看反汇编代码

 

当我们使用new来开辟空间时,new会先调用operator new(0C81140h)再调用这个自定义类型的构造函数。

让我们执行一下代码看看

 

通过运行结果我们发现,用new开辟空间时会调用构造函数。

那么operator new又是什么呢

我们可以看到,调用operator new时也是调用malloc来开辟空间,但与malloc有所不同的是,当开辟空间失败时,new会抛出bad_alloc 类型异常,而malloc在开辟空间失败会返回一个NULL 

4.delete和free的区别 

对于内置类型来说delete与free差别也不大,但是对于自定义类型来说,当使用delete,delete会先调用析构函数处理掉类型的数据,再释放空间。

让我们看以下代码

#include<iostream>
using namespace std;
class A
{
public:
A()
{
cout << "A()" << endl;
}
~A()
{
cout << "~A()" << endl;
}
private:
int aa;
};
int main()
{
A* ptr1 = new A;
delete ptr1;
}

运行结果

可以看出使用new和delete分别调用了构造函数和析构函数

我们看看反汇编代码

 

我们可以看到delete先是调用了析构函数再调用了operator deletor()

那么这个operator delete里面有什么呢

这个operator delete里面其实就是free函数

4.总结


  通过上面的学习后,我们总结一下new/deletehe对不同类型实现原理的区别:
1.对内置类型
1.如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是: new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。
2.对自定义类型new的原理
     1.调用operator new函数申请空间;
     2.在申请的空间上执行构造函数,完成对象的构造;
     3.对自定义类型newT[N]的原理
        调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对
        象空间的申请。
    4.在申请的空间上执行N次构造函数
3.对自定义类型delete的原理
     1.在空间上执行析构函数,完成对象中资源的清理工作。
     2.调用operator delete函数释放对象的空间。
     3.对自定义类型delete[]的原理
        在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理。
       调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释
      放空间。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/weixin_67596609/article/details/130722926

最后,总结出malloc/free和new/delete的区别:

        1.malloc和free是函数,new和delete是操作符;
        2.malloc申请的空间不会初始化,new可以初始化;
        3.malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可如果是多个对象,[]中指定对象个数即可;
        4.malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型;
        5 .malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常;
        6.申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new 在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/weixin_67596609/article/details/130722926


原文地址:https://blog.csdn.net/Visual_progress/article/details/142830268

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