如何在C ++中正确使用动态分配的多维数组

How to properly work with dynamically-allocated multi-dimensional arrays in C++

本问题已经有最佳答案,请猛点这里访问。

如何定义C++中的动态多维数组?例如,二维数组?我试着用一个指向指针的指针,但不知何故它失败了。


首先应该认识到,C++中没有多维数组支持,既可以是语言特征,也可以是标准库。所以我们能做的任何事情都是对它的模仿。例如,我们如何模拟二维整数数组?这里有不同的选择,从最不合适到最合适。

不正确的尝试1。使用指向指针的指针

如果使用指向该类型的指针来模拟数组,那么二维数组是否应该使用指向该类型的指针来模拟?像这样?

1
int** dd_array = new int[x][y];

这是一个编译器错误。没有new [][]操作符,所以编译器很乐意拒绝。好吧,那怎么样?

1
2
int** dd_array = new int*[x];
dd_array[0][0] = 42;

编译的。当被执行时,它会崩溃并发出不愉快的消息。出了点问题,但怎么了?当然!我们确实为第一个指针分配了内存——它现在指向一个内存块,该内存块将x指针保存到int。但是我们从未初始化这些指针!让我们再试一次。

2

这不会产生任何编译错误,并且程序在执行时不会崩溃。任务完成了?不是那么快。记住,每次我们调用new时,都必须调用delete。好了,给你:

1
2
3
for (std::size_t i = 0; i < x; ++i)
    delete dd_array[i];
delete dd_array;

现在,这太糟糕了。语法很难看,手动管理所有这些指针…不。让我们放下它,做点更好的事情。

不太恰当的尝试2.使用std::vectorstd::vector

好啊。我们知道,在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]

这给了我们美妙的句法,表演和所有的荣耀。为了让我们的生活稍微好一点,我们甚至可以在一个一维向量的基础上构建一个适配器——但这是留给家庭作业的。