在C/C++中使用多维数组是不好的编程实践吗?

19

一些程序员似乎非常讨厌多维数组,而另一些人则认为它们还可以。我知道任何可以对多维数组执行的操作也可以对普通数组执行,因此它们在功能上是等效的。使用多维数组是否是不好的实践,还是无关紧要的?


考虑使用boost::multi_array作为替代方案。它解决了数组的一些问题,同时减少了嵌套向量的开销和笨拙语法。 - frankc
9个回答

12

你是否需要存储预先知道维度的多维数据?如果是,使用多维数组。

如果你不知道维度 (即,你将需要动态分配数组),那么你需要:

  • 分配一个一维数组并使用索引算术模拟 n 维数组,或者
  • 分配一个指向元素数组的指针数组以获得实际的多维数组语义

具体用例取决于情况,但通常我更喜欢前者,因为它使内存管理更简单,少了堆内存分配。无论哪种方法,随着维数增加,复杂度都会增加。但在我看来,由于额外的间接级别,后一种方法的复杂度增长速度要快得多。


此外,用一维数组模拟n维数组可以使程序运行更快,如果您按行列遍历数据,则连续的数据将被加载到数据缓存中。而动态分配的多维数组很可能会有更高的缓存未命中率,因为数据可能存储在不同的位置。 - hdl

4

多维数组相对于 Vector<Vector<>> 的优点:

  1. 易于输入 [ ][ ]。
  2. 兼容 C 语言。
  3. 概念上容易理解它在做什么。

缺点:

  1. 没有轻松检测边界。超出外部括号的边界通常会溢出到内部括号分配的内存中,使这些类型的错误真正痛苦难追踪。
  2. 锯齿形数组需要小心设置。向量模式很简单。
  3. 多维数组不仅是双指针,而且更复杂,使得正确地传递到函数成为一件麻烦事。大多数情况下,我看到它们只是作为双指针的原始地址传递,这会破坏编译器为您执行的内在数学计算。

基本上,对我来说,问题在于缺乏边界检查。


2
回复 #1:vector<vector<T>> a(1, vector<T>(1)); a[0][0] = ... 是可以的。 - Potatoswatter
当然,我使用过那个。但是它不像a[1][1]; 这么易于输入和直观,这也是为什么向量向量没有被充分利用的一个重要原因。如果需要的话,甚至可以使用typedef或宏(呃)来掩盖丑陋的部分。 - Michael Dorgan
2
除非我的使用情况是不规则的,否则我永远不会使用 vector<vector<>> - Ben Voigt

1

多维数组相对于 Vector<Vector<>> 有以下优点:

  • 易于理解。
  • 元素的搜索和排序非常容易。
  • 与 C 兼容。
  • 易于类型定义。

0

0

在C++中,我不喜欢多维数组,因为它们应该被替换为std::vector<std::vector<t> >。如果你想表示一个std::vector<std::basic_string<t> >,它们也特别重要。

多维数组是如此简单的原始数据类型,我很惊讶大多数人会关心它。然而,使用单个维度的设计可能比使用多个维度更好,其他所有条件相等的情况下。


0

可能可以将多维数据存储在单一数据数组中,但您必须自己跟踪索引。实际上,多维数组在内存中作为单个维度数组存储,并具有支持表示该数据为多维的语法。

如果您正在处理多维数据,则选择正确的工具(多维数组)是最合适的。


0

我没有看到那里有任何多维的东西。 - Ben Voigt
@Ben:添加了多维度方面的链接。 - Potatoswatter

0

0

我知道任何可以对多维数组进行的操作也同样可以对普通数组进行操作。

我不认为这完全准确。我们需要一个指针数组来存储像名字列表这样基本的东西,然后对其进行排序。或者需要指向指针的指针来存储可变长度的字符串,然后是这些字符串的列表。 由于原始问题仅涉及数组本身,因此无法看到如何在普通数组中以相等的轻松程度解决这些问题。请考虑不仅将字符串存储在1-D数组中(可能使用某种分隔符),而且还执行诸如排序之类的操作。


一个数组索引表达式等同于一个指针和偏移量的组合。参见 Kernighan & Ritchie 页码99。 - AruniRC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接