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

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

时间2025-06-20 20:18:37分类IT科技浏览4668
导读: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
Android中intent(Android ImageView使用详解(系列教程三))