声明多维数组时的异常

c++ Exception when declaring multidimensional arrays

本文关键字:异常 数组 声明      更新时间:2023-10-16

我对编程有点陌生,我遇到了一个声明3D和4D数组的问题。在main函数的开头有几个这样的声明,但我已经将问题缩小到这4个:

string  reg_perm_mark_name[64][64][64];
short   reg_perm_mark_node_idex[64][64][64];
short   reg_perm_mark_rot[64][64][64][4];
short   reg_perm_mark_trans[64][64][64][3];

当我用这些来运行我的程序时,我得到"System. "StackOverflowException"在我的可执行文件中。我更喜欢一种动态分配它们的方式,我现在的方式是临时的,我不确定如何正确声明数组指针。

我在4D数组reg_perm_mark_trans中使用的4个元素,例如,是[节点索引][区域索引][标记索引][xyz坐标]。而且,一次总共声明了35个多维数组。(其中大多数是1D和2D)我不确定这是否有帮助。

有人能告诉我如何使这些4d数组工作,或者如何使它们动态分配与指针或向量?请描述一下,我还在学习。

为简单起见,假设sizeof(string) == 2(可能更多),您试图在堆栈上分配(64^3)*9*2字节。结果是4,718,592字节,或大约4.5 MiB。最有可能的是,您的堆栈中没有4.5 MiB可用。

由于这些变量是在main()中声明的,因此有两种可能的解决方案:

  1. 申报static

  2. main()外部声明它们作为全局变量

这将导致它们在程序开始之前被分配,而不是在堆栈上。这两种方法的唯一区别是它们在其他函数中是否可见。

也可能有一种方法告诉编译器程序需要更多的堆栈空间,但我认为将它们设置为静态可能是更好的解决方案。如果它们在main()以外的函数中,则可能需要执行其他操作。

一个简单的解决方案是使用静态分配(即将数组移到任何函数之外,或将它们标记为static)。

请注意,如果您使用c++数组,那么使用和占用是相同的,但它们的行为就像适当的容器:

array<array<array<string,64>,64>,64> reg_perm_mark_name;

要不安全地使用动态分配,可以这样写:
auto reg_perm_mark_rot = new short[64][64][64][4];
// ...
delete[] reg_perm_mark_rot;

要安全地使用它,从c++ 14开始(注意最里面的维度得到特殊处理):

auto reg_perm_mark_rot = std::make_unique<short[][64][64][4]>(64);

当然,您可以使用array而不是c风格的数组与动态选项,但这样您将有一个额外的间接级别来使用数组

这一行:

string  reg_perm_mark_name[64][64][64]

在堆栈上声明64*64*64 = 262144个字符串。std::string通常是32字节,所以大约是8MB。最大堆栈大小通常为1MB。

可以使用std::vector动态声明数组。通常,多维std::vector可能有点麻烦,在访问元素时,最好声明一个一维向量并转换为单个索引:

std::vector<std::string> reg_perm_mark_name(64*64*64);
int i = 13;
int j = 27;
int k = 7;
reg_perm_mark_name[i + 64*j + 64*64*k] = "Hello world!";

但是在这种情况下,您可以通过使用std::array而不是内部类型的std::vector来非常有效地声明多维std::vectorstd::array的使用避免了太多的内存分配,因为它们有固定的大小。我会使用类型定义或使用别名来使声明更清晰:

using StrArray = std::array<std::string, 64>;
using StrArray2D = std::array<StrArray, 64>;
std::vector<StrArray2D> reg_perm_mark_name(64);
reg_perm_mark_name[3][4][7] = "Hello world!";