二维数组的动态分配(new)、初始化(memset)和撤销(delete)

本文详细介绍了C++中一维及二维动态数组的创建、初始化、释放等操作方法。通过实例展示了如何正确地使用new和delete操作符以及memset函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:http://hi.baidu.com/jian_fei_yang/item/cf49006f5d53620aa0cf0ffe


一维数组的动态分配,初始化和撤销都好说,几乎每一本C++教材都会做出详细的说明。具体如下:

动态分配(例如分配10个单元的): int *array=new int [10];

初始化:memset(array,0,sizeof(array));       (也可以利用一个for循环对其赋值初始化)

撤销:delete [] array;

下面来说二维数组的。

二维数组(n行m列)利用new来进行动态分配实际上相当于对n个m元数组进行动态分配,只不过我们不能一味的按照动态分配一维数组的方法来这项操作。MSVC目前还没有这般的人性化,具体应该这样做:

int **array;
array=new int *[10];
for(int i=0;i<10;i++)
         array[i]=new int [5];


   上面的操作完成了一个10行5列的二维数组array[10][5]的动态分配,可以看到我们先动态分配了一个10单元的数组的指针的指针的首地址**array,然后再对其每个首地址进行遍历,同时完成一个5单元的数组的动态分分配,并把首地址给*array[i],从而最终完成了二维数组array[10][5]的动态分配。我们可以依此类推得到三维以至多维的数组的动态分配方法。

二维数组的初始化:如果把一维数组初始化办法照搬过来就会发现对于动态分配的二维数组并不适用。这就要理解到memset这个函数三个参数的含义。MSDN对memset的描述如下:

memset

Sets buffers to a specified character.

void*memset(void*dest,intc,size_tcount);

可见memset只能作用于一个一维数组void*dest,因此最好的办法就是和二维数组的动态分配结合起来,new一个,memset一个。具体写法如下:

int **array;
array=new int *[10];
for(int i=0;i<10;i++)

{
         array[i]=new int [5];

       memset(array[i],0,5*sizeof(int));

}

可以看到这里的memset的第三个参数有了变化。这是很关键的!原因是sizeof一个指针时,返回值为指针本身的大小而不是指针指向区域的大小,所以第三个参数要指明明确的空间,不能sizeof(array[i])

二维数组的撤销:delete [] array

                            对于二维数组的动态分配与释放

首先,动态支持数组的分配,必须用 new 来进行创建一段堆内存,其它的存贮区域不允许动态分配的产生。

其次,C++并没有提供真正的动态多维数组语法,想动态分配数组,必须通过一维动态数组组合形成一个类似多维数组的存贮形式,并不像静态分配多维数组,它们的用法虽说有些地方有相似之处,但不完全相同。

再次,有些网友有一些很BT的分配方式。

例如:

int (*p)[4] = new int[3][4];

解释:可能有些初学者认为这样是可取的,也是利用 new 分配的数组,就可以是动态的,那你的想法就错了,它的分配必须得有最外层 const 的支持—

int x = 3, y = 4;
int (*p)[y] = new int[x][y];//error,y必须是const。

所以这种方式不能达到真正的动态分配二维数组的目的,只能相当于半自动化的一个分配方式。

那么如果依靠下面的这种方式是正确的:

例:

int x = 3, y = 4;
int *p = new int*[x];//创建一个动态 int* 型数组
for (int i = 0; i < y; ++i)
p[i] = new int [x]; //再创建一个动态 int 型数组

for (int i = 0; i < y; ++i)
{
delete p[i];//由里至外,进行释放内存。 ---------------我认为是delete [] p[i];!!!!!后来查到的帖子证实
p[i] = NULL;//不要忘记,释放空间后p[i]不会自动指向NULL值,还将守在原处,只是释放内存而已,仅此而已。
}
delete []p;
p = NULL;

它就是依靠一维数组的组合来完成,这样创建的动态数组就是一个全自动的个分配方式。

例(完美废人提供):

void * buf = malloc (x * y * sizeof (int) ); //这也是一个好方法,简单方便,但它是C里面的分配方式。

free(buf);//释放内存简单方便.

提示:千万不要有 int *p = new int[4][2]; 这样的错误写法。


### 如何使用 `memset` 初始化二维数组 在 C/C++ 中,可以利用 `memset` 函数来快速初始化一维或多维数组。对于二维数组而言,其本质是一块连续分配的内存区域,因此可以直接通过 `memset` 对整个二维数组进行初始化。 以下是具体实现方式: #### 使用 `memset` 初始化二维数组 假设有一个大小为 `rows × cols` 的二维整型数组 `array`,可以通过如下代码将其所有元素设置为特定值(如 0 或其他数值)。 ```c #include <stdio.h> #include <string.h> #define ROWS 3 #define COLS 4 int main() { int array[ROWS][COLS]; // 将二维数组中的所有元素初始化为 0 memset(array, 0, sizeof(array)); // 输出验证 for (int i = 0; i < ROWS; ++i) { for (int j = 0; j < COLS; ++j) { printf("array[%d][%d] = %d\n", i, j, array[i][j]); } } // 如果想将二维数组中的所有元素初始化为非零值(例如 1),需要注意字节填充问题 // 下面的例子会将每个字节设为 1,可能导致意外的结果 memset(array, 1, sizeof(array)); // 输出验证 for (int i = 0; i < ROWS; ++i) { for (int j = 0; j < COLS; ++j) { printf("array[%d][%d] = %d\n", i, j, array[i][j]); } } return 0; } ``` #### 关键点解析 1. **`memset` 参数说明** - 第一个参数是指向目标内存块的指针,在这里是二维数组名 `array`。 - 第二个参数是要填充值的单字节数值(注意:仅能按字节填充)。如果希望将整数类型的变量置为 0,则此方法有效;但如果尝试用非零值填充整数类型的数据,可能会导致意想不到的行为[^2]。 - 第三个参数表示要被覆盖的总字节数,这里传入的是 `sizeof(array)` 来确保整个二维数组都被处理到。 2. **注意事项** 当试图用非零值(比如 1)去调用 `memset` 填充整型数据时,由于计算机内部存储机制的原因,实际效果可能不符合预期。这是因为 `memset` 只能在字节级别操作,而像 `int` 这样的多字节类型会被逐字节赋值,从而形成错误的数值组合[^1]。 #### 示例运行结果分析 当执行上述程序的第一部分时,所有的二维数组元素都会显示为 0。然而,在第二部分中,尽管我们期望看到全是 1 的情况,但由于每四个字节构成的一个整数实际上接收到了重复的一系列单独位元组设定动作的影响,最终打印出来的可能是诸如 16843009 (`0x01010101`) 这类奇怪数字[^1]。 ### 结论 虽然可以用 `memset` 方便快捷地把一块内存空间里的全部单元都归零或者赋予某些特殊模式下的初始状态,但对于更复杂的场景尤其是涉及高级别的抽象数据类型定义的时候还是推荐采用循环语句逐一指定确切初值更为稳妥可靠一些。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值