C++和C语言之动态内存
C++
重要概念
1、栈内存
函数内部声明的变量占用的内存
2、堆内存
程序未使用的内存,可用于动态分配内存
动态内存
程序在运行时动态分配内存,有时我们不知道我们需要分配多少内存,而是到了运行时才能知道,这时就需要动态分配内存,而其它的分配方式叫静态分配内存。面对需求灵活性高的程序,动态内存的地位极为重要。
若需要查看应用场景示例,请在本文右侧导航栏跳转至“应用场景”。
正题
new
和 delete
运算符
new
运算符
用于为变量申请内存,其格式为
1 | <var-name> = new <data-type>; |
例:
1 | char *c[]; |
即为char指针变量c申请缓冲区大小为20个字节的内存空间,如果在实际开发中,数据大小超过了该缓冲区就会导致缓冲区溢出报错。
还有第二种用法:
1 | int *num = new num(); |
写了括号但不写其值,这种用法即是开辟一个内存空间并初始化为0
delete
运算符
delete 运算符通常用于将已经使用完了的内存或不用的内存释放,根据需求合理释放内存是一个很好的习惯,不及时释放内存在小型项目中数据较少也许一时半会不会出现太大的问题,但是在大型项目开发中不释放内存会导致客户端可用内存越来越少,直至程序崩溃或是其它更严重的后果。
使用方法
1 | delete <<return-type> *var-name>; |
示例:
1 |
|
注意
delete运算符在操作数组变量时有些特别
1 | //错误示范 |
1 | //正确示范 |
在对多维数组进行内存释放时,也有些不同,需要进行数组内存迭代释放。
这种写法是错误的:
1 | int **arr[5][7] = { /*...*/ }; |
1 | int **arr[5][7] = { /*...*/ }; |
1 | int **arr[5][7] = { /*...*/ }; |
正确写法:
1 | int **arr[5][7] = { /*...*/ }; |
大于二维的数组需要多次for循环嵌套删除数组:
1 | int ****arr[5][7][9] = { /*...*/ }; |
delete ptr
与 delete [] ptr
的区别
delete ptr
用于释放ptr所指向的内存
delete [] ptr
用于释放ptr指向的内存,还逐一调用数组中每个对象的 destructor
C语言
动态内存管理
注:同样适用于C++,但在一些地方与C有别。
C语言内存通过指针变量进行管理,普通变量由程序自行管理,当变量出了其作用域后自动销毁,该程序退出后所有指针变量和普通变量占用内存一并销毁。同时必须注意,在分配内存的时候,C++必须要做强制类型转换,C语言不作硬性的要求
重要头文件:<stdlib.h>
该头文件下4个重要函数
1 | - void *calloc(int num, int size); |
void *calloc(int num, int size);
作用:在内存中动态分配 num 个长度为 size 的连续空间,并且将每一字节都初始化为 0。该函数与malloc函数类似,但是不同之处在于 calloc 在分配后还会将每一字节都进行一次初始化操作,而malloc函数则只是进行分配而不负责初始化,在性能方面,calloc函数比不上malloc,在分配内存的时候并不是每次都需要进行初始化,因此选择malloc函数进行内存分配是最佳的选择。
void *malloc(int num);
作用:在堆区分配一块指定大小的内存空间,用来存放数据,该块内存在函数执行后不会被初始化,它们的值是未知的。
void free(void *address);
作用:该函数释放 address 指向的内存块,释放的是动态分配的内存空间。虽然程序退出后会销毁程序所有已分配的内存,但是内存在不再使用的时候,进行销毁是一个好习惯。
语法:
1 | free(<var-name>); |
void realloc(void *address, int newsize);
作用:该函数重新分配内存,把内存扩展或缩小到 newsize。
例如,我想把内存块扩展到200*sizeof(
1 | <var-name> = <var-data-type*>realloc(<var-name>, 200 * sizeof(<var-data-type>)); |
应用场景
假如你是李华,今年7岁,你在新学期的自我介绍活动中准备上台发表陈词。
若要在程序中构建出李华这一个人和发表陈词这件事,则必须包含李华的姓名与年龄还有性别,且它们都是已知量,我们还知道它们所占字符数,但是李华的陈词是不确定的,假定它是由神经网络生成的陈词,但这必须是在程序运行后才能知道李华的陈词的所占字符数,因此,就可以使用动态内存分配来解决这个问题了,因为动态内存分配是在程序运行时根据一定条件来分配相应的内存。
代码示例:
1 |
|