Ser*_*eyA -3 c++ arrays dynamic-arrays
如何在C++中定义动态多维数组?例如,二维数组?我尝试使用指针指针,但不知怎的,它失败了.
首先应该意识到C++中没有多维数组支持,无论是作为语言功能还是标准库.因此,我们可以做的任何事情都是对它的一些模仿.我们怎样才能模仿二维整数数组呢?这里有不同的选择,从最不适合到最合适.
如果使用指向该类型的指针模拟数组,那么应该使用指向该类型的指针来模拟二维数组吗?像这样的东西?
int** dd_array = new int[x][y];
Run Code Online (Sandbox Code Playgroud)
那是一个编译器错误.没有new [][]运算符,所以编译器很乐意拒绝.好吧,那怎么样?
int** dd_array = new int*[x];
dd_array[0][0] = 42;
Run Code Online (Sandbox Code Playgroud)
编译.在执行时,它会因令人不快的消息而崩溃.出了点问题,但是什么?当然!我们确实为第一个指针分配了内存 - 它现在指向一个内存块,它包含指向int的x指针.但我们从未初步化过这些指针!我们再试一次吧.
int** dd_array = new int*[x];
for (std::size_t i = 0; i < x; ++i)
dd_array[i] = new int[y];
dd_array[0][0] = 42;
Run Code Online (Sandbox Code Playgroud)
这不会产生任何编译错误,并且程序在执行时不会崩溃.任务完成?没那么快.记住,每次我们打电话给new,我们都必须打电话给delete.所以,你走了:
for (std::size_t i = 0; i < x; ++i)
delete dd_array[i];
delete dd_array;
Run Code Online (Sandbox Code Playgroud)
现在,那太可怕了.语法很丑,并且手动管理所有这些指针......不.让我们全力以赴,做一些更好的事情.
std::vector的std::vector好.我们知道在C++中我们不应该真正使用手动内存管理,这里有一个方便的说法std::vector.那么,我们可以做到这一点吗?
std::vector<std::vector<int> > dd_array;
Run Code Online (Sandbox Code Playgroud)
显然,这还不够 - 我们从未指定过这些数组的大小.所以,我们需要这样的东西:
std::vector<std::vector<int> > dd_array(x);
for(auto&& inner : dd_array)
inner.resize(y);
dd_array[0][0] = 42;
Run Code Online (Sandbox Code Playgroud)
那么,现在好吗?没那么多.首先,我们仍然有这个循环,它是一个痛苦的眼睛.更重要的是,我们严重损害了我们的应用程序的性能.由于每个单独的内部向量都是独立分配的,所以循环如下:
int sum = 0;
for (auto&& inner : dd_array)
for (auto&& data : inner)
sum += data;
Run Code Online (Sandbox Code Playgroud)
将导致迭代多个独立分配的内部向量.由于CPU只会缓存连续内存,因此不能完全缓存那些小的独立向量.当你无法缓存时会伤害性能!
那么,我们该怎么做呢?
我们根本就没有!当情境需要二维向量时,我们只是以编程方式使用一维向量并使用偏移量访问它的元素!这是我们的做法:
vector<int> dd_array(x * y);
dd_array[k * x + j] = 42; // equilavent of 2d dd_array[k][j]
Run Code Online (Sandbox Code Playgroud)
这给了我们精彩的语法,表现和所有的荣耀.为了让我们的生活稍微好一些,我们甚至可以在一维矢量上构建一个适配器 - 但这是留给家庭作业的.