C++二维数组

梦想不会自己发光,真正闪耀的是那个为梦狂奔的你。献给知行的孩子们!(Eric.He著)


  本教程将从 C++ 二维数组的概念、定义、引用、初始化到越界问题和实际应用,全面拆解 C++ 二维数组的核心用法,帮助你掌握这一基础且重要的编程工具。

教程目录导航

一、C++ 二维数组的核心概述

1.1 二维数组的基本概念

C++ 中的二维数组可以理解为“数组的数组”,是一种存储多行多列数据的复合数据结构,本质上是连续的内存空间中按“行优先”顺序存储的一维数组的扩展。

二维数组常用于描述具有行列结构的数据,例如:

二维数组的内存布局(以 2 行 3 列数组为例):


// int arr[2][3] = {{1,2,3}, {4,5,6}};
内存地址:  0x00  0x04  0x08  0x0C  0x10  0x14
存储值:     1     2     3     4     5     6
对应位置:arr[0][0] arr[0][1] arr[0][2] arr[1][0] arr[1][1] arr[1][2]
        

💡 核心特点:

二、C++ 二维数组的基本使用

2.1 二维数组的定义

二维数组的定义需指定“数据类型 + 数组名 + [行数] + [列数]”,核心语法如下:

语法格式:


// 静态二维数组(行数和列数必须是常量)
数据类型 数组名[行数][列数];

// 示例:定义一个3行4列的整型二维数组
int arr[3][4];

// 动态二维数组(C++11及以上,行数/列数可变量)
// 方式1:指针数组(每行可独立分配)
数据类型** 数组名 = new 数据类型*[行数];
for (int i = 0; i < 行数; i++) {
    数组名[i] = new 数据类型[列数];
}

// 方式2:一维数组模拟二维数组
数据类型* 数组名 = new 数据类型[行数 * 列数];
        

示例:静态二维数组定义


#include <iostream>
using namespace std;

int main() {
    // 定义2行3列的整型数组
    int score[2][3];
    // 定义4行2列的浮点型数组
    float price[4][2];
    // 定义5行5列的字符型数组
    char chessboard[5][5];
    
    cout << "二维数组定义完成" << endl;
    return 0;
}
        

示例:动态二维数组定义


#include <iostream>
using namespace std;

int main() {
    int rows = 3, cols = 4;
    // 动态分配二维数组(指针数组)
    int** arr = new int*[rows];
    for (int i = 0; i < rows; i++) {
        arr[i] = new int[cols];
    }
    
    cout << "动态二维数组分配完成" << endl;
    
    // 释放内存(先释放列,再释放行)
    for (int i = 0; i < rows; i++) {
        delete[] arr[i];
    }
    delete[] arr;
    arr = nullptr;
    
    return 0;
}
        

2.2 二维数组的引用

二维数组的引用需通过“行下标 + 列下标”定位元素,下标从 0 开始,核心语法:数组名[行下标][列下标]

场景 1:静态二维数组的引用


#include <iostream>
using namespace std;

int main() {
    // 定义并初始化3行2列数组
    int arr[3][2] = {{10,20}, {30,40}, {50,60}};
    
    // 引用单个元素
    cout << "第1行第1列元素:" << arr[0][0] << endl; // 输出10
    cout << "第2行第2列元素:" << arr[1][1] << endl; // 输出40
    cout << "第3行第1列元素:" << arr[2][0] << endl; // 输出50
    
    // 修改元素值
    arr[1][0] = 35;
    cout << "修改后第2行第1列元素:" << arr[1][0] << endl; // 输出35
    
    // 遍历整个二维数组(双重循环)
    cout << "\n遍历二维数组:" << endl;
    for (int i = 0; i < 3; i++) { // 行循环
        for (int j = 0; j < 2; j++) { // 列循环
            cout << arr[i][j] << " ";
        }
        cout << endl; // 每行结束换行
    }
    
    return 0;
}
        

场景 2:动态二维数组的引用


#include <iostream>
using namespace std;

int main() {
    int rows = 2, cols = 3;
    // 动态分配二维数组
    int** arr = new int*[rows];
    for (int i = 0; i < rows; i++) {
        arr[i] = new int[cols];
        // 给每行赋值
        for (int j = 0; j < cols; j++) {
            arr[i][j] = i * cols + j + 1; // 赋值1,2,3,4,5,6
        }
    }
    
    // 引用并打印动态数组
    cout << "动态二维数组元素:" << endl;
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
    
    // 释放内存
    for (int i = 0; i < rows; i++) {
        delete[] arr[i];
    }
    delete[] arr;
    arr = nullptr;
    
    return 0;
}
        

2.3 二维数组的初始化

C++ 支持多种二维数组初始化方式,核心包括完全初始化、部分初始化、省略行数初始化等。

方式 1:完全初始化(指定所有元素)


// 按行初始化,每行用{}包裹
int arr[2][3] = {{1,2,3}, {4,5,6}};
// 等价于(省略行分隔,按行优先顺序)
int arr[2][3] = {1,2,3,4,5,6};
        

方式 2:部分初始化(未初始化元素默认值为0)


#include <iostream>
using namespace std;

int main() {
    // 仅初始化第一行和第二行第一个元素
    int arr[3][3] = {{1,2}, {3}};
    
    // 遍历查看所有元素
    cout << "部分初始化后的数组:" << endl;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
    // 输出:
    // 1 2 0 
    // 3 0 0 
    // 0 0 0 
    return 0;
}
        

方式 3:省略行数初始化(编译器自动推导行数)


#include <iostream>
using namespace std;

int main() {
    // 省略行数,编译器根据初始化内容推导为2行3列
    int arr[][3] = {{1,2,3}, {4,5,6}};
    
    // 计算行数(总字节数 / 每行字节数)
    int rows = sizeof(arr) / sizeof(arr[0]);
    int cols = sizeof(arr[0]) / sizeof(arr[0][0]);
    
    cout << "数组行数:" << rows << ",列数:" << cols << endl; // 输出2行3列
    return 0;
}
        

方式 4:动态二维数组初始化


#include <iostream>
#include <cstring>
using namespace std;

int main() {
    int rows = 2, cols = 2;
    int** arr = new int*[rows];
    for (int i = 0; i < rows; i++) {
        arr[i] = new int[cols];
        // 方式1:逐个赋值
        arr[i][0] = i + 1;
        arr[i][1] = (i + 1) * 10;
        
        // 方式2:批量赋值(memset仅适用于字符/字节型,整型建议循环)
        // memset(arr[i], 0, cols * sizeof(int)); // 初始化为0
    }
    
    // 打印结果
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
    // 输出:
    // 1 10 
    // 2 20 
    
    // 释放内存
    for (int i = 0; i < rows; i++) {
        delete[] arr[i];
    }
    delete[] arr;
    return 0;
}
        

三、C++ 二维数组的越界问题

二维数组的下标越界是 C++ 中常见的错误,指访问了“行数/列数范围外”的元素,例如:3行3列数组访问 arr[3][0] 或 arr[0][3]。

⚠️ 越界危害:

错误示例:数组越界


#include <iostream>
using namespace std;

int main() {
    int arr[2][2] = {{1,2}, {3,4}};
    
    // 错误1:行下标越界(最大行下标为1,此处访问2)
    cout << arr[2][0] << endl;
    // 错误2:列下标越界(最大列下标为1,此处访问2)
    arr[0][2] = 5;
    
    return 0;
}
        

规避方案:


#include <iostream>
using namespace std;

int main() {
    const int ROWS = 3, COLS = 3;
    int arr[ROWS][COLS] = {{1,2,3}, {4,5,6}, {7,8,9}};
    
    // 正确做法:循环时严格限制下标范围
    for (int i = 0; i < ROWS; i++) { // i < ROWS 而非 i <= ROWS
        for (int j = 0; j < COLS; j++) { // j < COLS 而非 j <= COLS
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
    
    // 动态数组同理:用变量记录行数/列数,循环时严格校验
    int rows = 2, cols = 4;
    int** dynArr = new int*[rows];
    for (int i = 0; i < rows; i++) {
        dynArr[i] = new int[cols];
        for (int j = 0; j < cols; j++) {
            dynArr[i][j] = i * cols + j;
        }
    }
    
    // 释放内存
    for (int i = 0; i < rows; i++) {
        delete[] dynArr[i];
    }
    delete[] dynArr;
    return 0;
}
        

四、C++ 二维数组的典型应用场景


#include <iostream>
using namespace std;

int main() {
    // 矩阵加法示例:2行2列矩阵相加
    int mat1[2][2] = {{1,2}, {3,4}};
    int mat2[2][2] = {{5,6}, {7,8}};
    int res[2][2];
    
    // 矩阵加法
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
            res[i][j] = mat1[i][j] + mat2[i][j];
        }
    }
    
    // 输出结果
    cout << "矩阵加法结果:" << endl;
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
            cout << res[i][j] << " ";
        }
        cout << endl;
    }
    // 输出:
    // 6 8 
    // 10 12 
    return 0;
}
        

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
    // 3个学生,4门科目成绩
    float scores[3][4] = {{85.5, 90.0, 78.0, 92.5}, 
                          {76.0, 88.5, 91.0, 85.0},
                          {90.5, 87.0, 89.5, 93.0}};
    // 计算每个学生的平均分
    cout << "学生平均分:" << endl;
    for (int i = 0; i < 3; i++) {
        float sum = 0.0;
        for (int j = 0; j < 4; j++) {
            sum += scores[i][j];
        }
        float avg = sum / 4;
        cout << "第" << i+1 << "个学生:" << fixed << setprecision(1) << avg << endl;
    }
    return 0;
}
        

#include <iostream>
using namespace std;

int main() {
    // 5x5五子棋棋盘:0=空,1=黑棋,2=白棋
    int chessboard[5][5] = {{0,0,0,0,0},
                            {0,1,0,0,0},
                            {0,0,2,0,0},
                            {0,0,0,1,0},
                            {0,0,0,0,2}};
    
    // 打印棋盘
    cout << "五子棋棋盘:" << endl;
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            cout << chessboard[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}
        

五、注意事项

六、总结

本教程从 C++ 二维数组的概念、定义、使用到越界问题和实际应用,全面拆解 C++ 二维数组的核心用法。掌握二维数组的运用,是学习数据结构和算法的重要基础之一。


返回顶部