C++动态分配(new)二维数组的若干方法

写在前面

之前刷动态规划的题目,多需要用到二维数组(也许后面再优化成一维)。如果每次都按照给定数的范围直接声明为全局二维数组变量,又总觉得的不够优雅。查阅了一些网上的资料后,总结了一些使用方法,就写下这篇博文用以记录。

方法1——动态分配(new)一维数组,再强制类型转换为二维(个人使用,推荐指数:⭐⭐⭐⭐)

直接看例子

/** 假设需要根据两个string的长度建立二维数组 */
const int sz1 = str1.size(); 
const int sz2 = str2.size(); 

/** 动态分配内存 */
auto f = new int[sz1 * sz2];
auto dp = (int (*)[sz2])f;

/** 这里放置自己制造bug的操作*/
// abaabaaba, 直接dp[i][j]使用即可

/** 制造完了别忘记释放栈空间 */
delete[] f;
f = nullptr;
dp = nullptr;

注意,auto dp = (int (*)[sz2]f这条语句,sz2的大小一定要是后面使用二维数组时最低维的大小
如果按照上面的类型转换方式,下面这样写会出现bug(注意sz1和sz2的顺序):

for (int i = 0; i < sz2; ++i)
  for (int j = 0; j < sz1; ++j)
    // do something; 
    /** 其实大概率你啥也do不了,程序跑飞了 */

这个方法优点和缺点都很明显,灵活、完全和使用全局二维数组方法一样,且释放内存简单,但是使用存在危险性。如果觉得自己把握不住,建议先考虑其他方法。


另外,请读者考虑一下,可以使用如下的二重指针代替一维数组的指针进行类型转换吗?

auto f = new int[sz1 * sz2];
auto dp = (int **)f; /** 二重指针真的可以吗?*/

若觉得可行的话,可能对二维数组和二重指针的理解出现了偏差。试想,我们按照dp存储的地址值a去寻址,得到地址a中存储的值b,再按照值b去寻址的话会发生什么?(本例中,b的值的根本不是地址,而是数组的值!)

C++动态分配(new)二维数组的若干方法

我们思考后也不难理解,为什么声明二维数组的形参类型或者是强制类型转换时,一定要正确指定最低维的大小。

方法2——分配一维数组,以二维数组的方式使用(推荐指数:⭐⭐⭐)

其实如果不是非要追求“传统”的使用二维数组的方式,也可以不用强制类型转换的方法。

只需要把握一点:二维数组的所有元素,在内存中是连续排列的。

那么我们可以按照如下的方式使用分配的二维数组:

/** 假设需要根据两个string的长度建立二维数组 */
const int sz1 = str1.size(); 
const int sz2 = str2.size(); 

/** 动态分配内存 */
auto f = new int[sz1 * sz2];

/** 给每个元素赋值 */
for (int i = 0, idx = 1; i < sz1; ++i)
    for (int j = 0; j < sz2; ++j, ++idx)
        f[i * sz2 + j] = idx; /** 相当于 arr[i][j] = idx; */

/** 别忘记释放堆空间 */
delete[] f;
f = nullptr;

与方法一大同小异,因此注意事项也一样,注意f[i * sz2 + j]中sz2是最低维的大小。

方法3——多次动态分配(也需要多次释放)(推荐指数:⭐⭐)

简单说,就是动态分配一维数组,然后把这些数组的指针存储到一个数组元素为一维数组的数组中。
代码如下:

/** 假设需要根据两个string的长度建立二维数组 */
const int sz1 = str1.size(); 
const int sz2 = str2.size(); 

/** 分配一个数组元素为一维数组的数组 */
auto dp = new int *[sz1];

/** 给数组每个元素赋值 */
for (int i = 0; i < sz1; ++i)
  dp[i] = new int[sz2];

/** 这里放置自己制造bug的操作*/
// abaabaaba

/** 制造完了别忘记释放堆空间 */
for (int i = 0; i < sz1; ++i)
  delete[] dp[i];

delete[] dp;

注意最后要先释放元素的内存。

(小声说,应该很少有人用这种方法?)

方法4——使用vector(推荐指数:⭐⭐⭐⭐⭐)

前面的几种方法多少是不太 idiomatic C++,最后当然要请出我们的STL。

没什么说的,直接看代码:

vector<vector<int> > dp(str1.length(), vector<int>(str2.length(), 0));

优点是不用再担心内存释放的问题,并且vector有很多方便的成员函数可以使用。

另外,在刷题的时候如果要判断二维vector是否为空,可以使用如下语句:

if (dp.empty() || dp[0].empty()) 
  return ;

原文链接:https://www.cnblogs.com/yang5sui/p/17311997.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++动态分配(new)二维数组的若干方法 - Python技术站

(0)
上一篇 2023年4月17日
下一篇 2023年4月17日

相关文章

  • C++实现一个线程安全的map

    本文是使用ChatCPT生成的,最终的代码使用起来没问题。代码是通过两轮对话完善的,后面把对话合并后跑不出理想效果就没尝试了。 第一轮对话 请求 c++11实现一个线程安全的map,使用方法与std::map保持一致,实现[]运算符 回复 以下是一个简单的线程安全的map实现,可以使用[]运算符来访问和修改map中的元素: //代码省略,后面一起给出 该实现…

    C++ 2023年5月7日
    00
  • 第四部分:Spdlog日志库的核心组件分析-logger

    Spdlog是一个快速且可扩展的C++日志库,它支持多线程和异步日志记录。在本文中,我们将分析Spdlog日志库的核心代码,探究其实现原理和代码结构。 Spdlog的基本架构 上一篇文章介绍了spdlog的五个主要组件,其中最重要是Logger、Sink和Formatter其中,Logger负责日志的记录和管理,Sink负责将日志输出到不同的目标(比如控制台…

    C++ 2023年4月18日
    00
  • 玩一玩 Ubuntu 下的 VSCode 编程

    一:背景 1. 讲故事 今天是五一的最后一天,想着长期都在 Windows 平台上做开发,准备今天换到 Ubuntu 系统上体验下,主要是想学习下 AT&T 风格的汇编,这里 Visual Studio 肯定是装不了了,还得上 VSCode,刚好前几天买了一个小工控机,这里简单记录下 零到一 的过程吧。 二:搭建一览 1. VSCode 安装 在 U…

    C++ 2023年5月3日
    00
  • STL容器之queue

    是什么 循环队列, FIFO先进先出 怎么用 初始化 //C11 deque<int> deq{1,2,3,4,5}; //拷贝构造,可以拷贝deque queue<int> que(deq); //100个5 queue<int> que2(100,5); //运算符重载 que2 = que; 操作 //队尾添加元素 …

    C++ 2023年4月17日
    00
  • MordernC++之左值(引用)与右值(引用)

    左值与右值 C++中左值与右值的概念是从C中继承而来,一种简单的定义是左值能够出现再表达式的左边或者右边,而右值只能出现在表达式的右边。 int a = 5; // a是左值,5是右值 int b = a; // b是左值,a也是左值 int c = a + b; // c是左值,a + b是右值 另一种区分左值和右值的方法是:有名字、能取地址的值是左值,没…

    C++ 2023年4月17日
    00
  • 驱动开发:通过MDL映射实现多次通信

    在前几篇文章中LyShark通过多种方式实现了驱动程序与应用层之间的通信,这其中就包括了通过运用SystemBuf缓冲区通信,运用ReadFile读写通信,运用PIPE管道通信,以及运用ASYNC反向通信,这些通信方式在应对一收一发模式的时候效率极高,但往往我们需要实现一次性吐出多种数据,例如ARK工具中当我们枚举内核模块时,往往应用层例程中可以返回几条甚至…

    C++ 2023年4月30日
    00
  • 07、【算例】openfoam带孔盘体应力分析

    官网:https://doc.cfd.direct/openfoam/user-guide-v9/platehole$FOAM_TUTORIALS/stressAnalysis/solidDisplacementFoam下的案例 1、网格划分 /*——————————–*- C++ -*—————…

    C++ 2023年4月18日
    00
  • 【Visual Leak Detector】配置项 AggregateDuplicates

    说明 使用 VLD 内存泄漏检测工具辅助开发时整理的学习笔记。本篇介绍 VLD 配置文件中配置项 AggregateDuplicates 的使用方法。同系列文章目录可见 《内存泄漏检测工具》目录 目录 说明 1. 配置文件使用说明 2. 设置是否显示重复的泄漏块 2.1 测试代码 2.2 AggregateDuplicates = no 时的输出 2.3 A…

    C++ 2023年4月18日
    00
合作推广
合作推广
分享本页
返回顶部