首页IT科技c语言定义一个二维数组,并给二维数组赋值(C++ 使用 new 创建二维数组)

c语言定义一个二维数组,并给二维数组赋值(C++ 使用 new 创建二维数组)

时间2025-07-30 12:25:49分类IT科技浏览5296
导读:1. 直接创建 C++ 使用 new 创建二维数组最直接的方法就是 new T[M][N]。返回的指针类型是 T (* [N],它是指向数组的指针,可以直接使用数组下标形式访问元素。释放内存直接使用delete[]。示例代码:...

1. 直接创建

C++ 使用 new 创建二维数组最直接的方法就是 new T[M][N]              。返回的指针类型是 T (*)[N]              ,它是指向数组的指针                        ,可以直接使用数组下标形式访问元素                        。释放内存直接使用delete[]        。示例代码:

#include <iostream> class A { public: A() { std::cout << "A::A" << std::endl; } ~A() { std::cout << "A::~A" << std::endl; } int x; }; int main() { A (*p)[3] = new A[2][3]; delete[] p; }

执行结果:

A::A A::A A::A A::A A::A A::A A::~A A::~A A::~A A::~A A::~A A::~A

可以看到 A 的构造函数和析构函数正常执行          。如果觉得 T (*)[N] 繁琐        ,可以直接使用 auto p = new T[M][N]                        。三维数组甚至更高维数组都可以使用这种方法            。例如          ,三维数组使用 new T[M][N][O] 进行创建                        ,依旧使用 delete[] p 进行释放      。

为什么可以这样写?因为这种多维数组和普通的多维数组都是通过一维数组实现的                       。例如            ,int a[6][8]      ,实际上编译器会转化为 int b[6 * 8] 一维数组                。然后每次访问二维数组 a[i][j] 相当于访问 b[i * 8 + j]   。从二维              、三维数组的转化过程中可以发现一些规律                      。

T a[M][N] --> T b[M * N], a[i][j] --> b[i * N + j] T a[M][N][O] --> T b[M * N * O], b[i][j][k] --> b[i * N * O + j * O + k]

编译器进行下标转换时                       ,并没有用到第 0 维的大小                ,而其它维的大小都是必须的                    。这也就是为什么下面代码能正确执行。

int a[2][3]; int (*p)[3] = a;

由于多维数组本质上是一维数组   ,所以释放内存都是 delete[] p                      ,而没有奇怪的 delete[][] 语法                  。

2. 借助指针数组

还有一种方法就是先 new T*[M] 创建一个指针数组                    ,其每个元素保存每一行的首个元素的地址,再使用 new T[N] 创建每一行                        。示例代码如下:

A** p = new A*[2]; for (int i = 0; i < 2; ++i) { p[i] = new A[3]; } for (int i = 0; i < 2; ++i) { delete[] p[i]; } delete[] p;

这种方法非常繁琐                  ,首先 new T*[M] 不能写成 new (T(*)[M])                        ,因为它是指针数组而不是数组指针    。其次    ,需要对每一行调用 new T[N]              。释放内存时              ,要先使用 delete[] 释放每一行                        ,再调用 delete[] 释放数组指针                        。这几个步骤一步都不能错        ,不然就出现野指针或者内存泄漏        。这段代码我也是用 Address Sanitizer 和 Leak Sanitizer 检查一遍才写对          。

这种方法唯一的好处就是可以创建交错数组(Jagged Array)          ,也就是每一行的大小不一样                        。例如:

A **p = new A *[2]; p[0] = new A[3]; p[1] = new A[4]; for (int i = 0; i < 2; ++i) { delete[] p[i]; } delete[] p;

3. 借助 std::vector

可以用 std::vector 对上面这种方法进行包装                        ,使其更加易用            。示例代码如下:

std::vector<std::vector<int>> v{ std::vector<int>(3), std::vector<int>(4) }; std::cout << v[0].size() << " " << v[1].size() << std::endl;

这段代码创建了一个二维数组            ,第 0 行有 3 个元素      ,第 1 行有 4 个元素      。这种方法既能创建交错数组                       ,也不需要手动释放内存                       。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
无法删除 文件或目录损坏且无法读取(无法删除文件提示无法读源文件或磁盘) 指针相关知识(指针知识点总结)