C/C++二维数组创建&内存分配

发布于:2025-08-13 ⋅ 阅读:(14) ⋅ 点赞:(0)

一、传统“指针的指针”写法(行不连续)

适用场景:行列都在运行期确定,且每行长度可不同(锯齿数组)。

C写法
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int rows = 3, cols = 4;

    /* 1. 先给行指针数组分配空间 */
    int **arr = (int **)malloc(rows * sizeof(int *));
    if (!arr) { perror("malloc rows"); return 1; }

    /* 2. 再给每一行分配列空间 */
    for (int i = 0; i < rows; ++i) {
        arr[i] = (int *)malloc(cols * sizeof(int));
        if (!arr[i]) { perror("malloc cols"); return 1; }
    }

    /* 3. 使用:arr[i][j] = ... */
    for (int i = 0; i < rows; ++i)
        for (int j = 0; j < cols; ++j)
            arr[i][j] = i * cols + j;

    /* 4. 打印验证 */
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j)
            printf("%2d ", arr[i][j]);
        putchar('\n');
    }

    /* 5. 释放:先逐行,再释放行指针 */
    for (int i = 0; i < rows; ++i)
        free(arr[i]);
    free(arr);
    return 0;
}
cpp写法
int rows = 3, cols = 4;

// 1. 先分配行指针数组
int** arr = new int*[rows];

// 2. 再给每一行分配列空间
for (int i = 0; i < rows; ++i)
    arr[i] = new int[cols];

// 3. 使用,赋值
for (int i = 0; i < rows; ++i)
    for (int j = 0; j < cols; ++j)
        arr[i][j] = i * cols + j;

/* 4. 打印验证 */
for (int i = 0; i < rows; ++i) {
    for (int j = 0; j < cols; ++j)
        printf("%2d ", arr[i][j]);
    putchar('\n');
}
// 4. 释放:先逐行,再释放行指针
for (int i = 0; i < rows; ++i)
    delete[] arr[i];
delete[] arr;
#include <vector>
#include <iostream>

int main() {
    // 3 行 4 列,全部初始化为 0
    int rows = 3;
    int cols = 4;
    std::vector<std::vector<int>> arr(rows, std::vector<int>(cols, 0));

   // 使用,赋值
	for (int i = 0; i < rows; ++i)
	    for (int j = 0; j < cols; ++j)
	        arr[i][j] = i * cols + j;

	/* 4. 打印验证 */
	for (int i = 0; i < rows; ++i) {
	    for (int j = 0; j < cols; ++j)
	        printf("%2d ", arr[i][j]);
	    putchar('\n');
	}
}

内存示意图:
在这里插入图片描述
缺点:
行与行之间内存不连续,缓存命中率低。
需要多个 new,释放顺序易出错。

二、一次性分配连续内存(推荐)

适用场景:行列已知,需要整块连续内存,效率高,易与 C API 交互。

c写法
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int rows = 3, cols = 4;

    /* 1. 一次性申请所有元素 + 行指针数组 */
    int **arr = (int **)malloc(rows * sizeof(int *));
    int  *data = (int *)malloc(rows * cols * sizeof(int));


    /* 2. 让行指针指向连续块的正确偏移 */
    for (int i = 0; i < rows; ++i)
        arr[i] = data + i * cols;   // 关键一步

    /* 3. 使用与赋值 */
    for (int i = 0; i < rows; ++i)
        for (int j = 0; j < cols; ++j)
            arr[i][j] = i * cols + j;

    /* 4. 打印 */
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j)
            printf("%2d ", arr[i][j]);
        putchar('\n');
    }

    /* 5. 释放:只需两步,顺序随意 */
    free(data);
    free(arr);
    return 0;
}
cpp写法
#include <iostream>

int main() {
    int rows = 3;
    int cols = 4;

    // 1. 一块连续内存存全部元素
    int** arr = new int*[rows];
    int* flat = new int[rows * cols];
    /* 2. 让行指针指向连续块的正确偏移 */
    for (int i = 0; i < rows; i++)
    		arr[i] = flat + i * cols;

    // 3. 像二维数组一样用
    for (int i = 0; i < rows; ++i)
        for (int j = 0; j < cols; ++j)
            arr[i][j] = i * cols+ j;

    // 4. 打印验证
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j)
            std::cout << arr[i][j] << ' ';
        std::cout << '\n';
    }

    // 5. 释放:先指针数组,再数据块
    delete[] arr;
    delete[] flat;
    return 0;
}

内存示意图:
data -> [0][1][2][3][4][5][6][7][8][9][10][11] // 连续

优点:

只有一段内存,缓存友好,易 delete[] data 一步释放。

三、极简“扁平化”写法(无二级指针)

如果你不需要 arr[i][j] 语法,可直接用一维指针模拟二维访问:

int rows = 3, cols = 4;
int *a = (int *)malloc(rows * cols * sizeof(int));
a[i * cols + j] = value;   // 访问元素

free(a);

网站公告

今日签到

点亮在社区的每一天
去签到