不要在C++(或C)中使用多维数组。
为什么?为什么我不应该在C++或C中使用多维数组?
他的这个声明是什么意思?
随后,另一位用户回复了这条评论:
哪些问题呢?Basile是正确的。在C/C++中声明3D数组是可能的,但会引起太多问题。
我经常使用多维数组,并没有发现使用它们有任何缺点。相反,我认为它只有优点。
使用多维数组是否存在任何问题,我不知道吗?
有人能解释一下他们的意思吗?
不要在C++(或C)中使用多维数组。
为什么?为什么我不应该在C++或C中使用多维数组?
他的这个声明是什么意思?
哪些问题呢?Basile是正确的。在C/C++中声明3D数组是可能的,但会引起太多问题。
使用多维数组是否存在任何问题,我不知道吗?
有人能解释一下他们的意思吗?
std::array
,堆上分配多维std::vector
,后两者的访问等等...。std::vector<double>
的std::vector
:std::vector<std::vector<double>> v;
v
中的每个 std::vector
对象都是连续分配的。此外,v
中的 std::vector<double>
中的所有元素都是连续分配的。然而,并非所有在 v
中存在的 double
都在连续的内存中。因此,根据您访问这些元素的方式(访问次数、访问顺序等),与包含所有 double
的连续内存中的单个 std::vector<double>
相比,一个 std::vector
的 std::vector
可能会非常慢。你不能同时回答C和C++的这个问题,因为这两种语言以及它们处理多维数组的方式存在根本性的差异。所以这个回答包含了两个部分:
在C++中,多维数组几乎没什么用处,因为你不能使用动态大小来分配它们。除最外层外的所有维度大小都必须是编译时常量。在我遇到的几乎所有多维数组用例中,尺寸参数都不是在编译时知道的,因为它们来自于图像文件或一些仿真参数等。
在某些特殊情况下,实际上可能会在编译时就知道这些维度的大小,在这些情况下,在C++中使用多维数组就没有问题。在所有其他情况下,你需要使用指针数组(设置繁琐)、嵌套的std :: vector<std :: vector<std :: vector<...>>>
,或者使用1D数组并手动计算索引(容易出错)。
C允许使用真正的动态大小的多维数组,自C99以来就成为可能。这被称为VLA,并且它允许你在堆栈和堆上创建完全动态大小的多维数组。
然而,有两个注意点:
You can pass a multidimensional VLA to a function, but you can't return it. If you want to pass multidimensional data out of a function, you must return it by reference.
void foo(int width, int height, int (*data)[width]); //works
//int (*bar(int width, int height))[width]; //does not work
You can have pointers to multidimensional arrays in variables, and you can pass them to functions, but you cannot store them in structs.
struct foo {
int width, height;
//int (*data)[width]; //does not work
};
void*
),但这并不容易。由于它不是一个经常使用的功能,只有很少的人知道如何正确地使用它。
C和C ++都允许您在编译时使用具有已知尺寸的多维数组,这些数组没有上述缺点。
但是它们的效用大大减少:只有在有许多情况下需要使用多维数组且无法在编译时得知涉及的大小的幽灵时,您才能使用它们。例如,图像处理:在打开图像文件之前,您不知道图像的尺寸。同样,任何物理模拟:直到程序加载其配置文件之前,您都不知道工作域的大小。等等。
因此,为了有用,多维数组必须支持动态大小。
data[(z*depth + y)*height + x]
的方式。这将编译成与 C 中 data[z][y][x]
表达式相同的代码,只是有点难以阅读和正确理解。我通常不会使用指针数组,因为它们设置和拆除非常繁琐,而且性能也不如索引计算方法。 - cmaster - reinstate monica所指的“问题”是没有正确使用结构,走出了数组的某个维度的末尾。如果您知道自己在做什么并且小心编码,它将完美地工作。
我经常在C和C ++中使用多维数组进行复杂矩阵操作。这在信号分析和信号检测以及用于模拟中分析几何体的高性能库中非常频繁。我甚至没有考虑动态数组分配作为问题的一部分。即使对于某些有界问题来说,具有重置功能的定型数组也可以节省内存并提高复杂分析的性能。对于较小的矩阵操作,可以在库中使用缓存,而对于每个问题基础上的更大的动态分配,则可以使用更复杂的C ++ OO处理。
float val = the1DArray[rowIdx*rowSize+colIdx];
)。 - Jeremy Friesnerstd::size_t N, M, L;
std::cin >> N >> M >> L;
int *** arr = new int**[N];
std::generate_n(arr, N, [M, L]()
{
int ** sub = new int*[M];
std::generate_n(sub, M, [L](){ return new int[L]; });
return sub;
});
// use arr
std::for_each_n(arr, N, [M](int** sub)
{
std::for_each_n(sub, M, [](int* subsub){ delete[] subsub; });
delete[] sub;
});
delete[] arr;
With:
std::vector<int> vec(N * M * L);
gsl::multi_span arr(vec.data(), gsl::strided_bounds<3>({ N, M, L }));
// use arr
a[4][3][2]
这样的数组的多维索引,并希望稍后将其替换为动态内容,则会留下更多的重构工作。 - Lemon Dropint x [6] [7] [8]
),你应该问自己将使用什么代替;int x [6 * 7 * 8]
?int ***x;
?valarray<int> x
?...许多替代方案将具有相同或更糟的问题。 - Yakov Galka