找回密码
 中文实名注册
查看: 303|回复: 0

【教程】C++ 二维数组

[复制链接]

704

主题

1096

帖子

2万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
22189
发表于 2021-8-18 19:06:18 | 显示全部楼层 |阅读模式
1、关于定义二维数组
先说在前面,一般的我们说的C/C++中的二维数组是定义在栈中的二维数组。比如定义了一个array[3][4],那就指的是定义了一个三行四列的矩阵形状的二维数组,如下图所示。这样的矩阵在内存中是以箭头右边的方式存放的,也就是说实际上我们定义的二维数组在内存中仍然像是一维数组那样连续存储的。可以想象为把一个矩阵一层层伸展铺平。



因此可以使用如下方法定义二维数组:

方法一 直接确定二维数组的行和列数
/* 可以使用下面的方法来初始化二维数组
* 也就是直接将二维数组铺平写成一维数组的形式*/
int array[3][4 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

/* 可以使用标准的二维数组的初始化方式*/
int array[3][4
] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};

方法二 不用指明二维数组的行数但要指明列数
下面的一种写法本质上是定义了一个数组指针

/* 经典的写法*/
int array[][4];

/* 一种更帅的写法本质上是定义了一个数组指针*/
int(*array)[4];

方法三 动态分配的方式这种写法比较灵活在定义的时候不需要指明二维矩阵的行数和列数
/* 使用动态分配内存的形式用malloc*/
int ** array     // array[M][N
]
array = (int **)malloc(M * sizeof(int * ));
for(int i=0 ; i < M ; i++) {
    array[i
] = (int *)malloc(N * sizeof(int));
}

// 释放
for(int i=0 ; i < M ; i++)
    free(array[i]);
free(array);

/* 使用动态分配内存的形式用new*/
int ** array    // array[M][N
array = new int*[M
]
for(int i=0 ; i < M ; i++) {
    array[i
] = new int[N];
}

// 释放
for(int i=0 ; i < M ; i++)
    delete[] array[i];
delete[] array;

不过按照这种形式实现的二维数组本质上已经不是我们之前说的传统的二维数组 了采用此种方法定义的二维数组的结构如下图所示这样的二维数组在堆上分配内存也就是说这样实现的二维数组本质上已经是指针数组了使用这样的方式分配二维数组空间之后可以使用array[i][j进行数组的读写操作没有问题但是应该知道不同行的内存空间不一定连续这是因为每一行的数组的内存都是使用malloc分配的多次使用malloc分配的内存空间并不一定是连续的这与在栈上分配的二维矩阵有着根本的不同比如同样的对于顶底的二维数组array[3][4不能再使用array[0][4来访问array[1][0
]这样会导致地址越界就是因为地址不一定连续了


2 二维数组的传参写法
使用二维数组作为参数可以有以下几种写法

1 使用动态分配内存的方式申请空间可以使用**传递参数
希望在使用二维数组的时候保持良好的编程习惯使用哪种方法定义的就使用哪种方式传参这样对于保持良好的编码习惯有好处对于别人阅读你的代码也有好处

#include <iostream>
using namespace std;

int func1(int **arr) {
    cout << arr[0][0];
    arr[0][2
] = 20;
    return 0;
}

int main()
{
    int ** array
    int row = 3;
    int col = 4;
    array = (int **)malloc(row * sizeof(int *))
    for (int i=0 ; i < row ; i++) {
        array[i
]= (int *)malloc(col * sizeof(int));
        }
    memset(*array, 0, sizeof(int)*row*col);

    array[0][1
] = 100;
    func1(array);
    cout << array[0][2];
    return 0;
}

2,使用二维数组的传统定义方法传递参数
如果把数组名作为函数的参数的话在编译的时候这个数组参数会自动退化为指针因此以下两种写法虽然不同但在编译之后是一样的数组会退化成数组指针

#include <iostream>
using namespace std;

/*以下两种写法本质上是一样的*/
int func1(int(*arr)[4]) {
    cout << arr[0][0 << endl;
    arr[0][2 = 20;
    return 0;
}

int func2(int arr[][4]) {
    cout << arr[0][0 << endl;
    arr[0][2 = 20;
    return 0;
}

int main()
{
    int array[3][4 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

    array[0][1 = 100;
    func1(array);
    cout << array[0][2 << endl;
    return 0;
}

正是因为这个问题在定义如下类似求数组大小的函数的时候必须将数组引用传递!否则数组会退化为一个指针无法正确的使用sizeof运算符求出数组a所占内存空间大小

template <class T>
int GetArrayLen(T& a)
{
    return sizeof(a)/sizeof(a[0]);
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?中文实名注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 中文实名注册

本版积分规则

小黑屋|东台市机器人学会 ( 苏ICP备2021035350号-1;苏ICP备2021035350号-2;苏ICP备2021035350号-3 )

GMT+8, 2024-12-4 01:10 , Processed in 0.042405 second(s), 30 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表