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

C++ 使用 new 创建二维数组的更多相关文章

  1. C语言 动态创建二维数组

    /*C语言 如何动态创建二维数组 转化为一维数组申请数组,创建和释放都比较简单 */ #include <stdlib.h> #include <stdio.h> #inclu ...

  2. Python创建二维数组(关于list的一个小坑)

    0.目录 1.遇到的问题 2.创建二维数组的办法 3.1 直接创建法 3.2 列表生成式法 3.3 使用模块numpy创建 1.遇到的问题 今天写Python代码的时候遇到了一个大坑,差点就耽误我交作 ...

  3. c/c++ 图的创建(二维数组法)

    c/c++ 图的创建(二维数组法) 图的概念 图由点和线组成 知道了图中有多少个点,和哪些点之间有线,就可以把一张图描绘出来 点之间的线,分有方向和无方向 创建图 创建图,实际就是创建出节点,和节点之 ...

  4. C#中创建二维数组,使用[][]和[,]的区别

    C#中,我们在创建二维数组的时候,一般使用arr[][]的形式,例如 int[][] aInt = new int[2][]; 但声明二维数组还有一种方法,是使用arr[,]的形式.两者有什么区别呢? ...

  5. c++ 用new创建二维数组~创建指针数组【转】

    #include <iostream> using namespace std; void main() { //用new创建一个二维数组,有两种方法,是等价的 //一: ] = ][]; ...

  6. c++用vector创建二维数组

    1 vector二维数组的创建和初始化 std::vector <int> vec(10,90); //将10个一维动态数组初始为90std::vector<std::vector& ...

  7. stl vector创建二维数组

    vector<vector<); for (auto it = v.begin(); it != v.end(); it++) { ; (*it).reserve();//预留空间为5,但 ...

  8. c++中创建二维数组的几种方法

    一.用new申请内存空间 int **dp=new int*[n];//动态申请二维数组nxm ;i<n;++i){ dp[i]=new int[m]; } 二.用malloc申请内存空间 ; ...

  9. typescript 创建二维数组

    private mouseView: Mouse private mouseArray: Array<Array<any>> = new Array<Array<a ...

  10. 【转】C++动态创建二维数组,二维数组指针

    原作者博客:蒋国宝的IT技术博客 今天完成一道题目需要自己用指针创建一个二维的数组,不得不承认指针的确是恶心. int **result; ; ; result = new int*[row]; ; ...

随机推荐

  1. laravel 报错 AUTH` failed: ERR Client sent AUTH, but no password is set

    明明没有设置redis密码.访问时候却报错 在代码里面的databases.php 改成这样就可以了.predis新版也会有取不到passwor的时候.改成我截图那样也可以.他默认取的是default ...

  2. win10本地python第三方库安装成功,但是pycharm项目无法使用解决方案

    一.背景win10本地python第三方库安装成功,但是pycharm项目无法使用解决方案如本地安装的python中的request库,在pycharm项目中居然无法使用,比较郁闷 pip list ...

  3. 二、python基本数据类型

    一. 字面量 代码中,被写在代码中的固定的值,称之为字面量 Python常用6种值(数据)类型 字符串(string) :又称文本,是由任意数量的字符如中文.英文.各类符号.数字等组成.所以叫做字符的 ...

  4. Spring中过滤器(Filter)和拦截器(Interceptor)的区别和联系

    在我们日常的开发中,我们经常会用到Filter和Interceptor.有时同一个功能.Filter可以做,Interceptor也可以做.有时就需要考虑使用哪一个比较好.这篇文章主要介绍一下,二者的 ...

  5. 三十三、HPA实现自动扩缩容

    通过HPA实现业务应用的动态扩缩容 HPA控制器介绍 当系统资源过高的时候,我们可以使用如下命令来实现 Pod 的扩缩容功能 $ kubectl -n luffy scale deployment m ...

  6. Java安全之Tomcat6 Filter内存马

    Java安全之Tomcat6 Filter内存马 回顾Tomcat8打法 先回顾下之前Tomcat789的打法 这里先抛开 7 8之间的区别, 在8中,最后add到filterchain的都是一个fi ...

  7. webRTC demo

    准备: 信令服务 前端页面用于视频通话 demo github 地址. 前端页面 为了使 demo 尽量简单,功能页面如下,即包含登录.通过对方手机号拨打电话的功能.在实际生成过程中,未必使用的手机号 ...

  8. JS 可编辑表格的实现(进阶)

    1.前言 在普通的可编辑表格的基础上,改进可编辑表格.数据来自外部的json(模拟服务端),通过json数据生成可编辑表格.根据实际情况,表格没有新增数据功能.表格的可编辑列,计算的列,每列的数据大小 ...

  9. ARM TrustZone白皮书部分阅读

    嵌入式系统安全的一些解决方法及缺陷 外部硬件安全模块:在主SoC之外包含一个专用的硬件安全模块或可信元件,e.g. 手机的SIM卡.隔离仅限于可以从非易失性存储器运行的相对静态程序 内部硬件安全模块: ...

  10. 2022春每日一题:Day 10

    题目:CF1110E Magic Stones 每次操作 c[i]变成c[i-1]+c[i+1]-c[i],那么显然,c[1]和c[n]是不会改变的,因此只要c[1]和t[1],c[n]和t[n]不相 ...