我想为C ++中的所有-1
初始化一个大型的二维数组(例如1000x1000,尽管我想更大一些)。
如果我的数组是一维的,我知道我可以做:
int my_array[1000];
memset(my_array, -1, sizeof(my_array));
但是,memset
不允许将数组的所有元素初始化为另一个数组。我知道我可以制作一个长度为1000000的一维数组,但是出于可读性的考虑,我更喜欢一个二维数组。我也可以在将二维数组初始化为所有0
之后遍历二维数组以设置值,但是这部分代码将在我的程序中运行很多次,我不确定这将有多快。实现此目标的最佳方法是什么?
编辑后添加了最少的可重复示例:
int my_array[1000][1000];
// I want my_array[i][j] to be -1 for each i, j
答案 0 :(得分:1)
使用GNU GCC,您可以:
int my_array[1000][1000] = { [0 .. 999] = { [0 .. 999] = -1, }, };
使用任何其他编译器,您需要:
int my_array[1000][1000] = { { -1, -1, -1, .. repeat -1 1000 times }, ... repeat { } 1000 times ... };
侧面说明:以下是分配,而不是初始化:
int my_array[1000][1000];
for (auto&& i : my_array)
for (auto&& j : i)
j = -1;
所做的事情与for(int i = 0; i <1000; i ++){for(int j = 0; j <1000; j ++){{my_array [i] [j] = -1; }}?
这取决于。如果编译器性能较差,则无需优化等即可进行编译,那么可以。很可能不会。无论如何,不要使用索引。我相信在这种情况下,range based for loop会大致翻译为:
for (int (*i)[1000] = my_array; i < my_array + 1000; ++i)
for (int *j = *i; j < *i + 1000; ++j)
*j = -1;
旁注:ch!计算每个循环的my_array + 1000
和*i + 1000
很麻烦。就像每个循环执行3次操作一样。这个CPU时间浪费了!可以轻松将其优化为:
for (int (*i)[1000] = my_array, (*max_i)[1000] = my_array + 10000; i < max_i; ++i)
for (int *j = *i, *max_j = *i + 1000; j < max_j; ++j)
*j = -1;
循环中使用的my_array[i][j]
转换为*(*(my_array + i) + j)
(请参见aarray subscript operator)。指针算术得出的值等于*(*((uintptr_t)my_array + i * sizeof(int**)) + j * sizeof(int*))
。计数操作my_array[i][j]
在幕后进行乘法,加法,解引用,乘法,加法,解引用-类似于六项操作。 (使用错误的或未优化的编译器时),您的版本可能会变慢。
也就是说,一个好的编译器应该将每个版本优化为相同的代码,如here所示。
这两个方法中的任何一个是否都比通过键入一百万个-1显式初始化它慢得多?
我相信分配每个数组元素(在这种特殊情况下,元素具有易于优化的类型int
)将比初始化快或慢。它实际上取决于您的特定编译器和体系结构。不良的编译器可能会非常慢地迭代数组元素,因此将永远花费很长时间。另一方面,静态初始化可以将值嵌入程序中,因此程序大小将增加sizeof(int) * 1000 * 1000
,并且在程序启动期间初始化程序的静态区域时将执行简单的memcpy
。因此,与经过适当优化的分配循环相比,就速度和大量只读存储器而言,您将一无所获。
答案 1 :(得分:1)
我有点惊讶。
我知道,它是C ++。而且,我永远不会使用纯C样式数组。
因此,被接受的答案也许是最好的。
但是,如果我们回到这个问题上
int my_array[1000];
memset(my_array, -1, sizeof(my_array));
和
int my_array[1000][1000];
// I want my_array[i][j] to be -1 for each i, j
然后,最简单,最快的解决方案与最初的假设相同:
int my_array[1000][1000];
memset(my_array, -1, sizeof(my_array));
没有区别。编译器甚至会对此加以优化,并使用快速汇编器循环指令。
Sizeof足够聪明。它将成功。并且内存是连续的:因此,它将起作用。快速。容易。
(好的编译器会对其他解决方案进行相同的优化)。
请考虑。
答案 2 :(得分:0)
如果数组是静态的,则将其放置在顺序内存中(检查this question)。因此char [1000] [1000]等于char [1000000](如果您的堆栈可以容纳那么多)。
如果数组是使用多维new创建的(例如char(*x)[5] = new char[5][5]
),那么它也是连续的。
如果不是(如果使用动态分配创建),则可以在my question中找到的解决方案将n维数组映射到单个数组。