在C++中要动态地开辟数组,需要使用new,那么如果要开辟M行N列的二维数组呢?需要我们首先开辟一个长度为M的指针数组,然后对于每个指针开辟一个长度为N的数组:
int **a = new int *[M];
for(int i = 0; i < M; i++){
a[i] = new int[N];
}
如果这时我想让数组的每个值都为0呢?如何使用memset()?
如果只想通过一次调用就达到你的目的,那就错了。首先我们看一下memset()的函数原型:
void *memset(void *s, int ch, size_t n);
函数解释:将s中当前位置后面的n个字节(typedef unsigned int size_t)用ch替换并返回s。
需要注意的是memset作用于当前位置后的n个字节,意味着这是一块连续的内存空间。而你每次用new开辟数组时并非连续(但new出来的一维数组是连续的),所以这就是错误所在。那么我们的做法可以是这样:
int **a = new int *[M];
for(int i = 0; i < M; i++){
a[i] = new int[N];
memset(a[i], 0, N * sizeof(int));
}
与此对应的,如果我们不再需要这些数组,如何释放呢?看代码:
for(int i = 0; i < M; i++){
delete[] a[i];
a[i] = NULL;
}
这里有个很重要的问题:无论是free还是delete,仅释放指针所指的内存空间与指针指向的对象,并未将指针置为NULL,即指针会成为一个野指针。如果不将其赋为NULL,则在后续操作中可能会出现意想不到的错误。
另一种方式:
说是另一种方式,实质上是把二维数组当成一维数组来开辟的。
int *p = new int [M * N];
如果访问第i行第j列的元素,可以通过a[i * N + j]的方式来访问。
其实两种方式的优缺点一看就明白:第一种方式开辟和释放数组时麻烦了一些,但是访问容易;第二种开辟和释放很简单,new的次数少,但是不易理解。
至于要选择哪一种,还是看个人喜好,任君选择吧~