动态内存分配
虽然通过数组就可以对大量的数据和对象进行有效地管理,但是很多情况下,在程序运行之前,我们并不能确切地知道数组中会有多少个元素。这种情况下,如果数组声明过大,就会造成浪费;声明过小,就会影响处理。
在C++中,动态内存分配技术可以保证程序在运行过程中按照需要申请适量内存,使用后释放,从而避免只使用数组时的两难情况。
常见动态内存分配方式
方式 | 特点 |
new和delete | C++关键字; 以具体类型为单位进行内存分配; 申请单个类型变量时可进行初始化 |
malloc和free | C语言stdlib.h库中提供的函数; 以字节为单位进行内存分配; 不具备内存初始化特性。 |
new/delete和new[]/delete[]
1. 定位
new和delete为C++中的关键字,通过特殊的语法可以组成表达式。可以用于动态申请空间,并可在申请之后进行必要的初始化。
2. 基本语法
①变量申请
用于分配内存以包含一个类型类型的单个元素。
②数组申请
用于分配类型类型的元素的块(数组),其中N是表示这些元素的量的整数值。
③初始化
用于初始化分配的内存。注意:此处所使用括号为圆括号而非方括号。
④释放内存
new/delete、new[]/delete[]配对使用,即用new申请的内存,需要使用delete释放;用new[]申请地内存,需要使用delete[]释放。
3. 作用机制
①new和delete
new 调用operator new标准库函数分配空间
=> 调用类型的默认构造函数
=> 初始化元素
=> 返回指针
delete 通过指针指向的析构函数,对打开的文件进行关闭
=> 调用operator delete释放内存
②new[]和delete[]
大致与上面相同,调用operator new[]与operator delete[] 函数对若干个数组对象释放内存。但是在对于 非内置类型 或有 自定义析构函数的类 类型,new[]会多分配四个字节以存储数组的大小,delete[]时则从数组对象指针的前面四个字节取出调用析构函数的次数,传入C++标准库中的operator delete[]函数的为将数组对象的指针值减4。
因此,仅仅在对象为 内置类型 或无自定义的析构函数的类 类型时,才可以使用delete来释放new[]申请的数组空间。
但是,尽管知道了这些,保险起见最好还是严格配对使用new/delete和new[]/delete[]。
malloc和free
1. 定位
malloc为C语言stdlib.h库中的函数,可以用于动态申请空间,在申请空间之后不会对内存进行必要的初始化。
C++可以兼容大部分C语言的内容,malloc/free这一申请/释放动态内存的方式在C++中用也是可以使用的。
2. 基本语法:
变量申请示例
用于以字节为单位进行内存分配,不具备内存初始化特性。返回指针的类型为void*,可以通过类型转换(如static_cast、(type)等)转换为想要的类型。
异常处理
C++提供了两种标准的检查内存分配成功与否的机制。
1. 处理异常(handling exceptions)
分配内存失败,类型为bad_alloc 的异常会被抛出,如果没有被特定的处理器处理,程序执行中止。
2. nothrow
当内存分配失败,不抛出bad_alloc 类型的异常,而是返回null指针,然后程序继续执行。示例:
在上面的情况下,内存分配的失败情况可以通过检测foo指针是否为空来判断。
参考资料:
[1]http://www.cplusplus.com/doc/tutorial/dynamic/
[2]http://www.cplusplus.com/reference/new/
[3]https://blog.csdn.net/hazir/article/details/21413833
[4]https://blog.csdn.net/qq_40416052/article/details/82493916
作者/ 王政和 张腾飞