我对编程有些新意,我遇到了声明3D和4D数组的问题。我在main函数的开头有几个这样的声明,但是我把问题缩小到了这四个:
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数组工作,或者如何让它们用指针或向量动态分配?请说明,我还在学习。
答案 0 :(得分:4)
为了简单起见sizeof(string) == 2
(可能更多),你试图在堆栈上分配(64 ^ 3)* 9 * 2字节。结果是4,718,592字节,或大约4.5 MiB。最有可能的是,您的堆栈中没有4.5 MiB可用。
由于这些变量是在main()
中声明的,因此您有两种可能的解决方案:
声明他们static
。
将它们作为全局变量在main()
之外声明。
这将导致在程序启动之前分配它们,而不是在堆栈上分配它们。这两种方法的唯一区别在于它们是否在其他功能中可见。
可能还有一种方法可以告诉编译器程序需要更多的堆栈空间,但我认为将它们设置为静态可能是更好的解决方案。如果他们使用main()
以外的函数,你可能需要做其他事情。
答案 1 :(得分:2)
这一行:
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::vector
代替std::array
来为内部类型非常有效地声明多维std::vector
。 std::array
的使用避免了太多的内存分配,因为它们具有固定的大小。我会使用typedef或使用别名来使声明更清晰:
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!";
答案 2 :(得分:2)
一个简单的解决方案是使用静态分配(即将数组移到任何函数之外,或将它们标记为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风格数组,但是你可以使用额外的间接级别来使用数组。