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

 更新时间:2023年01月12日 08:41:58   作者:mkckr0  
这篇文章主要介绍了C++ 使用 new 创建二维数组实例的相关资料,需要的朋友可以参考下

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 创建二维数组实例的文章就介绍到这了,更多相关C++ 使用 new 创建二维数组内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • c语言数据结构与算法之顺序表的定义实现详解

    c语言数据结构与算法之顺序表的定义实现详解

    这篇文章主要介绍了c语言数据结构与算法之顺序表的定义实现详解,用顺序存储的方式实现线性表顺序存储,把逻辑上相邻的元素存储在物理位置上也相邻的存储单元中,元素之间的关系由存储单元的邻接关系来体现,需要的朋友可以参考下
    2023-08-08
  • 简单总结C语言中的运算符优先级

    简单总结C语言中的运算符优先级

    这篇文章主要介绍了C语言中的运算符优先级,文中简单总结了一些常用运算符的优先级顺序以及记忆技巧,需要的朋友可以参考下
    2016-05-05
  • VC6.0实现读取Excel数据的方法

    VC6.0实现读取Excel数据的方法

    这篇文章主要介绍了VC6.0实现读取Excel数据的方法,非常实用的功能,需要的朋友可以参考下
    2014-07-07
  • 解决Qt设置QTextEdit行高的问题

    解决Qt设置QTextEdit行高的问题

    这篇文章介绍了Qt设置QTextEdit行高的方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • C语言中main函数两个参数的作用

    C语言中main函数两个参数的作用

    这篇文章主要介绍了C语言中main函数两个参数的作用,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • Cocos2d-x保存用户游戏数据之XML文件是否存在问题判断方法

    Cocos2d-x保存用户游戏数据之XML文件是否存在问题判断方法

    这篇文章主要介绍了Cocos2d-x保存用户游戏数据之XML文件是否存在问题判断方法,请注意代码中包含大量注释,需要的朋友可以参考下
    2014-09-09
  • C语言中getchar()的返回类型为什么是int详解

    C语言中getchar()的返回类型为什么是int详解

    这篇文章主要给大家介绍了关于C语言中getchar()的返回类型为什么是int的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • C语言 以数据块的形式读写文件详解及实现代码

    C语言 以数据块的形式读写文件详解及实现代码

    本文主要介绍 C语言 以数据块的形式读写文件,这里对相关知识资料做了整理,并附代码示例,以便大家学习参考,有学习此部分知识的朋友可以参考下
    2016-08-08
  • Qt6.0+vs2019环境配置的实现教程

    Qt6.0+vs2019环境配置的实现教程

    这篇文章主要介绍了Qt6.0+vs2019环境配置的实现教程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • C++实现LeetCode(38.计数和读法)

    C++实现LeetCode(38.计数和读法)

    这篇文章主要介绍了C++实现LeetCode(38.计数和读法),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07

最新评论