首页 > 编程语言 >C++ 使用 new 创建二维数组

C++ 使用 new 创建二维数组

时间:2023-01-12 12:07:58浏览次数:38  
标签:AA std int C++ 二维 数组 new delete

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 个元素。这种方法既能创建交错数组,也不需要手动释放内存。

标签:AA,std,int,C++,二维,数组,new,delete
From: https://blog.51cto.com/u_15839417/6003939

相关文章

  • 【C++11】chrono库
    chrono是c++11中的时间库,提供计时、时钟等功能学习chrono,关键是理解里面精度、时间段、时间点的概念1.精度时钟节拍(时间精度),后面的时间段和时间点都是基于精度的计算......
  • javascript集合的使用 new Set()使用
        参考:https://blog.csdn.net/weixin_52941842/article/details/126338193......
  • 5月TIOBE编程语言:Python持续第一,C++将冲击前三
    新的TIOBE5月编程语言榜单出炉了,让我们一起看一下这次有哪些新看点:Python稳居第一,C++或将冲至Top3本次的榜单和4月相比没有明显变化,Top5依然是Python、C、Java、C++......
  • 74. 搜索二维矩阵
    问题链接https://leetcode.cn/problems/search-a-2d-matrix/description/解题思路我们可以确定,数据是有序的。所以我们有2种办法用二分来解决。第一种,我们可以写个下标......
  • C++ STL的简单应用(vector容器专题)
    #include<iostream>#include<string>#include<stdlib.h>#include<vector>//#include<algorithm>usingnamespacestd;//vector容器的简单应用voiddemo1(){......
  • c++ unit test via gtest
    //model/book.h#pragmaonce#include<iostream>usingnamespacestd;classbook{public:book()=default;~book()=default;book(constbook&......
  • C++ 使用 new 创建二维数组
    1.直接创建C++使用new创建二维数组最直接的方法就是newT[M][N]。返回的指针类型是T(*)[N],它是指向数组的指针,可以直接使用数组下标形式访问元素。释放内存直接使......
  • 【教你学Qt桌面端开发】pt1:浅谈Qt:特色C++主义类库
    还在为头脑简单看不懂代码而发愁吗?还在为思想浅薄只会人云亦云、拾人牙慧、鹦鹉学舌而遭人鄙夷吗?《教你写代码》,从另一维度解读代码,让你成为见解独特的黑马观众。教你学Q......
  • C++ 扩展的显示类型转换
      ......
  • C++实现顺序队列(循环队列)相关操作代码
    #include<iostream>#include<cstdlib>usingnamespacestd;#defineMAXSIZE100#defineOK1#defineERROR0#defineOVERFLOW-1typedefintStatus;typedefintElemtype......