C语言中的动态数组
C语言中的动态数组就是动态内存分配的知识
首先,先看C语言的那些小秘密之动态数组https://blog.csdn.net/bigloomy/article/details/6615012,里面有关内存分配的内容,请看C语言的那些小秘密之内存分配https://blog.csdn.net/bigloomy/article/details/6581706,如果对其中的realloc()函数,malloc()函数,calloc()函数对应里面的eg看不懂的话,可以参考malloc的用法和意义https://blog.csdn.net/chf_1/article/details/78688557这篇blog
C++动态数组的知识主要是new,delete(这俩与内存分配有关)以及vector容器
参考的blog:C++中如何定义动态数组https://blog.csdn.net/singebogo/article/details/70477737
C++ 动态数组 vector 详解https://blog.csdn.net/c20182030/article/details/69667965
顺便强烈推荐:C语言进阶重点、难点与疑点解析。这本书很不错
1.C语言的内存分配有三个函数
1)realloc()函数
原型:extern void *realloc(void *mem_address, unsigned int newsize);
语法:指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)。
头文件:#include
功能:先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域,同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。
返回值:如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NULL。
注意:这里原始内存中的数据还是保持不变的。当内存不再使用时,应使用free()函数将内存块释放。
2)malloc()函数
原型:extern void *malloc(unsigned int num_bytes);
头文件:在Visual C++6.0中可以用malloc.h或者stdlib.h。
功能:分配长度为num_bytes字节的内存块
返回值:如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL。当内存不再使用时,应使用free()函数将内存块释放。
说明:该函数返回为void型指针,因此必要时要进行类型转换。(这就是为啥要在malloc函数之前加强制类型转换)
3)calloc()函数
calloc是一个C语言函数
功 能: 在内存的动态存储区中分配n个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。
跟malloc的区别:
calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不初始化,里边数据是随机的垃圾数据。
用 法: void *calloc(unsigned n,unsigned size);
头文件:stdlib.h或malloc.h
重头戏
C语言动态数组
动态数组的内存空间是从堆动态分配的,是通过执行代码而为其分配存储空间。当程序执行到我们编写的分配语句时,才为其分配。对于静态数组,其创建非常方便,使用完也无需释放,要引用也简单,但是创建后无法改变其大小是其致命弱点!对于动态数组,其创建麻烦,使用完必须由程序员自己释放,否则将会引起内存泄露。但其使用非常灵活,能根据程序需要动态分配大小。所以相对于静态数组的来说我们对于使用动态数组有很大的自由度。
在创建动态数组的过程中我们要遵循一个原则,那就是在创建的时候从外层往里层,逐层创建;而释放的时候从里层往外层,逐层释放
那篇blog中讲解了一维动态数组、二维动态数组、以及三维动态数组的创建与释放,由于一维和二维用的比较多,所以我着重看一下这俩,三维的话看兴趣吧,目前找工作要紧,所以就不太深入
一维动态数组的创建:
主要还是calloc()、malloc()、realloc()函数创建动态空间
#include
#include
int main()
{
int n1,i;
int *array;
printf("请输入所要创建的一维动态数组的长度:");
scanf("%d",&n1);
array=(int*)calloc(n1,sizeof(int));
for(i=0;i
运行结果为:
特此说明:在以后的运行结果部分,我均会附上文字结果,以防图片打开失败。
请输入所要创建的一维动态数组的长度:4
0 0 0 0
1 2 3 4 Press any key to continue
在此我使用的是calloc()函数来分配的,同时也使用两个for语句来打印数组元素,我们发现第一个打印输出的数组元素值均为0,在此也是为了加深读者对于calloc()函数的印象我特地使用了它来分配
二维数组的创建(需要双重指针):
#include
#include
int main()
{
int n1,n2;
int **array,i,j;
printf("请输入所要创建的动态数组的第一维长度:");
scanf("%d",&n1);
printf("请输入所要创建的动态数组的第二维长度:");
scanf("%d",&n2);
array=(int**)malloc(n1*sizeof(int*)); //第一维
for(i=0;i
运行结果为:
请输入所要创建的动态数组的第一维长度:3
请输入所要创建的动态数组的第二维长度:3
1 2 3
4 5 6
7 8 9
Press any key to continue
有了上面的代码我们再来说动态数组的建立就简单了,以二维为例,先说创建,还记得我们上面说的创建的原则嘛:从外层往里层,逐层创建。
array=(int**)malloc(n1*sizeof(int*)); //第一维
以上是我们创建二维动态数组的最外层,创建好了最外层那么我们接下来就是要创建次外层了。
array[i]=(int*)malloc(n2* sizeof(int));//第二维
在创建次外层的过程中我们使用了一个for循环语句,千万别忘了使用for循环语句,这是绝大多数人的一个易错点。
创建好了接下来我们该讲到释放了,而释放的时候从里层往外层,逐层释放。刚刚与我们上面的创建相反,在以上代码中我们首先使用了下面一个for循环来释放里层。
for(i=0;i
free(array[i]);//释放第二维指针
}
在通过以下语句来释放外层。
free(array);//释放第一维指针
================================================================================================
C++语言中的动态数组
c++要求定义数组时,必须明确给定数组的大小,要不然编译通不过
如: int Array[5];正确
int i=5;
int Array[i]; 错误 因为在编译阶段,编译器并不知道 i 的值是多
所以,new 动态定义数组来解决定义长度未知的数组。
因为new 就是用来动态开辟空间的,所以当然可以用来开辟一个数组空间(这个是一维的)
这样,下面的语句:
int size=50;
int *p=new int[size]; 是正确的
二维动态数组的定义
int size=50
int (*p)[50]=new int [size][50]
便正确了。
由此可见,这种动态分配数组,仅对一维数组空间是真正动态分配的。
既然一维是真正的动态分配的话,那我们利用这一特性定义一个指针数组。
int **p= new int*[size];//定义指针数组
int *p[5];// 假若知道二维数组的行数为5
注意:指针数组定义了size个int型指针变量,用来存储地址
然后对指针数组中的每一个指针分配一个一维数组空间,这样便动态定义了二维数组
事实上,我认为指针数组的主要用途,就在于动态定义多维数组
for(int i=0;i
p[i]=new int[Column];
}
运行完毕后,一个二维数组便被动态的成功建立
size =6;
column =5
int **p=new int*[size];
for(int i=0;i
所生成的动态数组如下图所示:(6行5列)
最后 ,因为调用了new, 千万千万别忘记在用完之后,将其所占资源 delete 掉
下面是delete方法:
for(int i=0;i
动态数组vector的具体用法,参考我最上面说明的blog,我只对我理解的关键点进行相应解释
1,首先它所提出的代码,结果为啥是这样的?
可以看出vector的内存是翻倍了,这就是vector容器的特点吧,对于size从3到5的解释是:这时候新增加一个i=4,所以这个时候v=[1,2,3,4],而前面的last=4,所以不执行if语句了,新的i=5,所以这个时候v=[1,2,3,4,5],而capacity翻倍了a=8,而8不等于这个4,所以就输出了,得到此时size()=5的结果。
与此同时,blog作者经过其它的实验,为啥得出下面的结论的原因,两个结合看,事半功倍
当动态数组内的元素比动态数组长度多一时,动态数组长度翻倍!
也就是说:if(v.size()-1==v.capacity()) v.resize(v.capacity()*2);
eg:size()=5-1等于capacity=4的时候,capacity翻倍为8了
blog作者的建议是:
而长度翻倍是很花时间的。所以说做题的时候,记得事先把vector的长度拉得足够长,以免运行的时候,vector长度翻倍浪费时间。