How to properly work with dynamically-allocated multi-dimensional arrays in C++
如何定义C++中的动态多维数组?例如,二维数组?我试着用一个指向指针的指针,但不知何故它失败了。
首先应该认识到,C++中没有多维数组支持,既可以是语言特征,也可以是标准库。所以我们能做的任何事情都是对它的模仿。例如,我们如何模拟二维整数数组?这里有不同的选择,从最不合适到最合适。
不正确的尝试1。使用指向指针的指针如果使用指向该类型的指针来模拟数组,那么二维数组是否应该使用指向该类型的指针来模拟?像这样?
1 | int** dd_array = new int[x][y]; |
这是一个编译器错误。没有
1 2 | int** dd_array = new int*[x]; dd_array[0][0] = 42; |
编译的。当被执行时,它会崩溃并发出不愉快的消息。出了点问题,但怎么了?当然!我们确实为第一个指针分配了内存——它现在指向一个内存块,该内存块将x指针保存到int。但是我们从未初始化这些指针!让我们再试一次。
2这不会产生任何编译错误,并且程序在执行时不会崩溃。任务完成了?不是那么快。记住,每次我们调用
1 2 3 | for (std::size_t i = 0; i < x; ++i) delete dd_array[i]; delete dd_array; |
现在,这太糟糕了。语法很难看,手动管理所有这些指针…不。让我们放下它,做点更好的事情。
不太恰当的尝试2.使用好啊。我们知道,在C++中,我们不应该真正使用手动内存管理,并且这里有一个方便的EDOCX1 3。那么,也许我们能做到?
1 | std::vector<std::vector<int> > dd_array; |
显然,这还不够——我们从未指定这些数组的大小。所以,我们需要这样的东西:
1 2 3 4 5 | std::vector<std::vector<int> > dd_array(x); for(auto&& inner : dd_array) inner.resize(y); dd_array[0][0] = 42; |
那么,现在好了吗?没那么多。首先,我们仍然有这个环,这是一个眼睛痛。更重要的是,我们严重损害了应用程序的性能。由于每个内部向量都是独立分配的,因此这样的循环:
1 2 3 4 | int sum = 0; for (auto&& inner : dd_array) for (auto&& data : inner) sum += data; |
将导致对许多独立分配的内部向量进行迭代。由于CPU只缓存连续内存,所以这些小的独立向量不能完全缓存。当您无法缓存时,会损害性能!
那么,我们该怎么做呢?
正确尝试3-一维!我们根本就没有!当情况需要二维向量时,我们只需通过编程方式使用一维向量,并使用偏移访问它的元素!我们就是这样做的:
1 2 | vector<int> dd_array(x * y); dd_array[k * x + j] = 42; // equilavent of 2d dd_array[k][j] |
这给了我们美妙的句法,表演和所有的荣耀。为了让我们的生活稍微好一点,我们甚至可以在一个一维向量的基础上构建一个适配器——但这是留给家庭作业的。