【C++基础学习】二维数组的动态分配及参数传递

1. C语言动态分配二维数组
(1)已知第二维
char (*a)[N];//指向数组的指针

a = (char (*)[N])malloc(sizeof(char *) * m);
printf("%d\n", sizeof(a));//4,指针
printf("%d\n", sizeof(a[0]));//N,一维数组

free(a);

(2)已知第一维

char* a[M];//指针的数组
int i;
for(i=0; i<M; i++)
a[i] = (char *)malloc(sizeof(char) * n);
printf("%d\n", sizeof(a));//4*M,指针数组
printf("%d\n", sizeof(a[0]));//4,指针

for(i=0; i<M; i++)
    free(a[i]);

(3)已知第一维,一次分配内存(保证内存的连续性)

char* a[M];//指针的数组
int i;

a[0] = (char *)malloc(sizeof(char) * M * n);
for(i=1; i<M; i++)
a[i] = a[i-1] + n;
printf("%d\n", sizeof(a));//4*M,指针数组
printf("%d\n", sizeof(a[0]));//4,指针

free(a[0]);

(4)两维都未知

char **a;
int i;

a = (char **)malloc(sizeof(char *) * m);//分配指针数组
for(i=0; i<m; i++)
{
a[i] = (char *)malloc(sizeof(char) * n);//分配每个指针所指向的数组
}

printf("%d\n", sizeof(a));//4,指针
printf("%d\n", sizeof(a[0]));//4,指针

for(i=0; i<m; i++)
{
free(a[i]);
}
free(a);

(5)两维都未知,一次分配内存(保证内存的连续性)

char **a;
int i;
a = (char **)malloc(sizeof(char *) * m);//分配指针数组
a[0] = (char *)malloc(sizeof(char) * m * n);//一次性分配所有空间
for(i=1; i<m; i++)
{
a[i] = a[i-1] + n;
}

printf("%d\n", sizeof(a));//4,指针
printf("%d\n", sizeof(a[0]));//4,指针
free(a[0]);
free(a);

2.C++动态分配二维数组
(1)已知第二维
char (*a)[N];//指向数组的指针
a = new char[m][N];

printf("%d\n", sizeof(a));//4,指针
printf("%d\n", sizeof(a[0]));//N,一维数组

delete[] a;

(2)已知第一维

char* a[M];//指针的数组
for(int i=0; i<M; i++)
    a[i] = new char[n];

printf("%d\n", sizeof(a));//4*M,指针数组
printf("%d\n", sizeof(a[0]));//4,指针

for(i=0; i<M; i++)
    delete[] a[i];

(3)已知第一维,一次分配内存(保证内存的连续性)

char* a[M];//指针的数组
a[0] = new char[M*n];
for(int i=1; i<M; i++)
a[i] = a[i-1] + n;

printf("%d\n", sizeof(a));//4*M,指针数组
printf("%d\n", sizeof(a[0]));//4,指针

delete[] a[0];

(4)两维都未知

char **a;
a = new char* [m];//分配指针数组
for(int i=0; i<m; i++)
{
a[i] = new char[n];//分配每个指针所指向的数组
}

printf("%d\n", sizeof(a));//4,指针
printf("%d\n", sizeof(a[0]));//4,指针

for(i=0; i<m; i++)
delete[] a[i];
delete[] a;

(5)两维都未知,一次分配内存(保证内存的连续性)

char **a;
a = new char* [m];
a[0] = new char[m * n];//一次性分配所有空间
for(int i=1; i<m; i++)
{
a[i] = a[i-1] + n;//分配每个指针所指向的数组
}

printf("%d\n", sizeof(a));//4,指针
printf("%d\n", sizeof(a[0]));//4,指针

delete[] a[0];
delete[] a;

多说一句:new和delete要注意配对使用,即有多少个new就有多少个delete,这样才可以避免内存泄漏!

3.静态二维数组作为函数参数传递
如果采用上述几种方法动态分配二维数组,那么将对应的数据类型作为函数参数就可以了。这里讨论静态二维数组作为函数参数传递,即按照以下的调用方式:
int a[2][3];
func(a);
C语言中将静态二维数组作为参数传递比较麻烦,一般需要指明第二维的长度,如果不给定第二维长度,则只能先将其作为一维指针传递,然后利用二维数组的线性存储特性,在函数体内转化为对指定元素的访问。
首先写好测试代码,以验证参数传递的正确性:
(1)给定第二维长度
void func(int a[][N])
{
printf("%d\n", a[1][2]);
}

(2)不给定第二维长度

void func(int* a)
{
printf("%d\n", a[1 * N + 2]);//计算元素位置
}
注意:使用该函数时需要将二维数组首地址强制转换为一维指针,即func((int*)a);


<think>好的,我现在需要回答用户关于C++中如何传递二维数组作为函数参数的问题。用户之前已经问过关于矩阵旋转的实现,其中涉及到二维数组的处理,现在他想了解不同的参数传递方法。我需要结合用户提供的引用内容,以及之前的回答,来整理出一个清晰的解释。 首先,我要回忆一下用户提供的引用内容。引用[1]提到了一数组作为参数的问题,比如使用固定大小或者const变量,但指出容易出错,因为函数内部无法获取数组的实际大小。引用[2]展示了二维数组作为参数的三种方式,特别是使用指针传递,将二维数组当作一处理。引用[3]讨论了数组作为返回值的例子,返回静态数组的指针。引用[4]则涉及动态二维数组的传递,使用二级指针和动态内存分配。 用户现在的问题是询问C++二维数组作为函数参数的传递方式。我需要列举不同的方法,并解释每种方法的优缺点,同时结合用户之前的矩阵旋转代码,其中使用了int**作为参数,这可能和动态数组有关。 首先,确定二维数组C++中的几种常见传递方式: 1. 固定大小的二维数组:例如void func(int arr[][3], int rows)。这种方法需要知道列的大小,但不够灵活。 2. 使用指针传递:将二维数组视为一数组,并手动计算索引,如引用[2]中的例子。 3. 二级指针传递:适用于动态分配二维数组,如用户之前旋转矩阵的函数中使用的int** matrix。 4. 使用数组指针:例如void func(int (*arr)[3], int rows),这种方式保留二维结构,但同样需要固定列数。 接下来需要分析每种方法的适用场景、限制以及代码示例。例如,固定大小的方法在列数固定时有效,但不适合动态数组动态分配的方法更灵活,但需要手动管理内存,容易出错。 还要注意用户之前提到的矩阵旋转函数,其中参数是int** matrix,并处理n*n的矩阵。这可能属于动态分配二维数组的情况,因此需要解释如何正确传递这样的参数,包括内存分配和释放的问题。 同时,引用[4]中的例子显示,动态分配二维数组可以通过int**传递,并且在函数中访问元素的方式是num[i][j]。但需要注意内存分配的连续性,动态分配的每一行可能是独立的内存块,这与真正的二维数组不同。 另外,用户提供的示例中存在将二维数组作为一指针传递的情况,例如引用[2]中的fun函数,传入的是int* array,并通过行和列数计算索引。这可能适用于将二维数组扁平化处理的情况。 在总结时,需要比较这些方法的优缺点,例如固定大小的限制、动态分配的灵活性但复杂性、以及指针运算的注意事项。同时,可能还要提到C++中更现代的解决方案,比如使用vector容器来简化内存管理,但用户的问题可能更关注原生数组的处理。 最后,确保回答结构清晰,分点说明每种方法,并给出相应的代码示例,帮助用户理解不同传递方式的具体实现。同时,结合用户之前的代码,解释为什么在旋转矩阵时使用int**参数,并强调正确传递二维数组的重要性。</think>在C++中传递二维数组作为函数参数主要有以下四种方法,根据内存分配方式和参数类型的不同,需选择适合场景的传递方式: --- ### 一、固定列宽的二维数组传递 #### 特点 - **适用场景**:已知列数的静态数组 - **语法限制**:必须显式指定第二长度 - **内存布局**:连续存储二维数组 ```cpp void printMatrix(int arr[][3], int rows) { for (int i = 0; i < rows; ++i) { for (int j = 0; j < 3; ++j) { std::cout << arr[i][j] << " "; } std::cout << "\n"; } } // 调用示例 int matrix[2][3] = {{1,2,3}, {4,5,6}}; printMatrix(matrix, 2); ``` --- ### 二、指针转一数组处理 #### 特点 - **适用场景**:任意二维数组(静态/动态) - **核心方法**:将二维数组视为连续内存块 - **索引计算**:通过公式`i * cols + j`定位元素 ```cpp void findMax(int* arr, int rows, int cols) { int maxVal = arr[0]; for (int i = 0; i < rows*cols; ++i) { if (arr[i] > maxVal) maxVal = arr[i]; } std::cout << "最大值: " << maxVal; } // 调用示例(静态数组) int a[2][3] = {{1,2,3}, {4,5,6}}; findMax(&a[0][0], 2, 3); ``` --- ### 三、动态数组的二级指针传递 #### 特点 - **适用场景**:动态创建的二维数组(每行独立分配) - **内存特点**:行数据可能不连续 - **参数类型**:`int**`(指向指针的指针) ```cpp void rotateMatrix(int** matrix, int n) { // 用户之前问题中的实现 // 行逆序与转置操作... } // 动态数组创建示例 int** createMatrix(int rows, int cols) { int** mat = new int*[rows]; for (int i = 0; i < rows; ++i) { mat[i] = new int[cols]; } return mat; } ``` --- ### 四、数组指针语法 #### 特点 - **适用场景**:保留二维数组类型信息 - **语法形式**:`int (*arr)[列数]` - **内存布局**:保证连续存储 ```cpp void transpose(int (*arr)[3], int rows) { for (int i = 0; i < rows; ++i) { for (int j = i+1; j < 3; ++j) { std::swap(arr[i][j], arr[j][i]); } } } // 调用示例 int table[3][3] = {{1,2,3}, {4,5,6}, {7,8,9}}; transpose(table, 3); ``` --- ### 关键差异对比表 | 方法 | 内存连续性 | 列数限制 | 适用场景 | 访问速度 | |---------------------|------------|----------|---------------------|----------| | 固定列宽 | 连续 | 必须指定 | 静态数组 | 最快 | | 一指针 | 连续 | 无 | 任意二维数组 | 较快 | | 二级指针 | 不连续 | 无 | 动态分配数组 | 较慢 | | 数组指针 | 连续 | 必须指定 | 静态数组/动态分配块 | 最快 | --- ### 应用建议 1. **图像处理**:推荐使用一指针方式处理连续像素数据[^2] 2. **矩阵运算**:动态分配时选择二级指针传递(如之前的旋转矩阵实现)[^1] 3. **硬件交互**:固定列宽方式适合与底层驱动交互的缓冲区 --- ### 注意事项 1. **内存泄漏**:动态数组必须配对使用`new[]`和`delete[]` 2. **度传递**:必须显式传递行数和列数(编译器无法推导)[^3] 3. **类型匹配**:静态数组动态数组的指针类型不可混用 --- ### 相关问题 1. 为什么动态二维数组的行数据可能不连续? 2. 如何用vector容器实现更安全的二维数组传递? 3. C++中如何返回二维数组
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值