动态开辟内存,就是在堆区,可以根据自己的需要开辟和释放。(用完一定得释放)?
1.C语言
1. (void*)malloc(size_t n);? // 传入一个需要开辟多少个字节的内存?(可以是一个常数,也可以是一个可以计算出的表达式),返回一个void*指针指向开辟内存的首地址。根据你存放数据的类型将返回指针强行转换成相应内存即可。
? ?要使用此函数得导入<stdlib.h>头文件,使用此函数的开辟的内存,使用free()函数释放
int *a = (int*)malloc(1024);//开辟1024个字节
free(a);
a = NULL;
上面代码,开辟了1kb的内存,存放int数据,所以要将其返回的void*指针强制转换为int*,返回赋值给指针a。试用结束,用free()释放这片内存。?
因为,我们释放了内存之后,但是指针a还存在,因为它指向的内存已经释放,我们是万万不能再去访问它,所以为了保险起见,释放完内存之后,将它指向NULL;?
2.c++?
c++中动态开辟内存使用new运算符。
int* test; // 定义一个指针,可以指向一片空间
int (*test1)[5]; // 定义一个指向二维数组的指针
test = new int; //使用new申请一个int空间
test = new int(10); // 使用new开辟一个int空间并且初始化为10
delete test; // 释放内存直接使用delete
int nub = 10;
test = new int[nub]; // 使用new申请nub个int类型的连续空间
test1 = new int[nub][5]; // 使用new申请一个nub行5列的二维数组。
// 必须是使用一个指向二维数组的指针才可以,所以使用test是不行的
// 只有第一个[]可以使用变量及相关表达式。第二个[]只能使用常量和常量表达
式
//使用下面形式释放一片空间([]号中不需要写多少,因为os有标记)
delete[] test;
delete[] test1;
// 注意:在使用delete释放申请到的内存时,必须使用我们用于指向这片内存(首地址),也就是我们申请内存
// 时,用于指向这片内存的指针,--在本例中为:test和test1,不可以是test+1等。
上面的代码就使用了new和delete运算符来实现动态内存分配的。??
?
意思是,使用malloc函数申请的内存可以通过delete释放。?
? ? ? ? ? ? 使用new运算符申请的内存可以通过free释放。?
int *m_pointer = (int *)malloc(1024); // 申请1kb
delete[] m_pointer; // 使用delete释放
int *n_pointer = new int; // 申请4个字节
free(n_pointer); // 使用free释放
?
因为,malloc和free都是函数,有调用上的开销。而c++中new和delete是运算符,所以new和delete的效率要高于malloc和free,所以我们平时在c++中建议使用后者。?
因为c++完全兼容C语言,所以也可以使用malloc和free来实现。?
?
比如:我们平时需要输入一组数据,因为我们最开始不知道这组数据的数量,之前我们可以定义一个数组来存储,但是数组不支持变量定义和动态变化-----所以我们只能将数组定义的尽可能的大一点。?
int a[1024];? ?当我们定义一个这样的数组时,我们可能只需要放十个数据在里面,这样就浪费了很多空间。?
使用动态分配存储的内存就可以降低这种的损耗。?
?
我们平时写程序时,一些局部变量等在栈中存储,但是栈内存是有限的,windows可能是1M-2M(因为要给别的程序预留),而如果我们想要创建使用很大一片内存,这时候,就可以从堆中使用, 堆的空间1G-2G一般。?
?
1. 堆区内存的生命周期? ----? ?从申请成功开始到释放。(这个过程是我们可以控制的)?。
2. 因为我们平时使用函数返回一个指针(变量地址)时,往往是不可以返回局部变量的,因为函数调用结束之后该变量对应的内存就被回收了,你再去访问那不就出问题了。?
如果想要返回函数内的创建的内存: 1. 使用static定义变量? ? 2. 使用动态开辟的内存(未释放的)?
内存泄漏:? ? 我们申请了内存,但是我们不使用,os也不知道,这其实就是内存泄漏。?
我们动态申请的内存使用完一定要释放掉,如果不释放,你不使用它,os又不知道,你再次去申请内存,一直不释放,就会导致很多空间浪费了,可使用的内存也会逐渐降,直到程序崩溃。?