为什么我应该使用简单的数组而不是容器类

Why should I use simple arrays rather than container classes?

本文关键字:容器类 数组 我应该 简单 为什么      更新时间:2023-10-16
使用

数组而不是容器可以更有效地完成什么(如果有的话(?

我最近了解了C++标准容器类。它们具有明显的优势,并解决了 C 型数组的常见问题。关于"为什么数组是邪恶的"的FAQ列表可以像这样粗略地总结:

1. subscripts are not checked
2. often it is required to allocate memory from the heap
3. not easy to insert elements in the middle
4. always passed as reference

我想在很多情况下,人们可以忍受这些缺点。但是,我对这个问题有点困惑,使用数组而不是容器可以更高效/更轻松地完成什么?还是实际上没有那样的东西,我真的不应该再关心数组了?

"但是,我对这个问题有点困惑,使用数组而不是容器可以更高效/更轻松地完成什么?">

好吧,如果你指的是 c 风格的数组,使用当前的 c++ 标准,经典标准 c++ 容器类的缺点就没有什么了(例如 std::vector ( 恕我直言。这些依赖于具有可分配内存(带new()(,这很可能是当前(操作系统/裸机(环境的限制,因为无法开箱即用。


当前标准提供了std::array,无需动态内存分配需求,但满足所有声明:

"1.不检查下标">

std::array进行下标检查

"2.通常需要从堆中分配内存">

这是客户的选择,它实际上与std::array一起分配。 无论如何,std::vector这样做就足够了。

"3.不容易在中间插入元素">

嗯,这是开箱即用std::array不能很好地支持的一点。但同样,std::vector和其他容器类很好地支持这一点(只要您的环境支持动态内存分配(

"4.总是作为参考传递">

std::array很好地支持通过引用传递,并且比使用 C 样式数组(不能(实现的要好得多。


尽管可能存在可重用对象实例池或蝇量级对象实例等特殊情况,但您可能希望使用放置new()运算符来解决。此类解决方案的实现通常涉及您将在原始 c 样式数组上进行操作。

内置数组是一个低级工具,界面有些尴尬。但是,需要它们来实现更好的类:C++的一个好处是它公开了许多低级工具来创建更高级别的抽象的有效实现。对我来说,内置数组的主要用途是:

  1. 实现更高层次抽象(如std::vector<T>std::array<T, N>(的机制(好吧,std::vector<...>和家族并没有真正使用内置数组,而是在内部处理原始内存(。
  2. 当我需要一个值数组使用堆栈上分配的一系列值初始化时,我会使用内置数组(std::array<...>无法推断参数的数量,任何使用 std::initializer_list<T> 进行初始化的东西都不会有固定的大小(。

尽管std::array<T, N>实际上只是对内置数组的[某些]功能的重写,但它具有调试实现可以断言所做出的假设的良好功能。

顺便说一句,你列出的不包括更大的问题:如果你有一个可变大小的数组,你需要给你的元素类型一个默认的构造函数。使用 C++11,默认构造函数至少可以默认(如果您的类需要另一个构造函数,这是一个问题(,这可以避免即将初始化的对象。但是,各种容器类消除了很多复杂性。

堆栈上的数组可能比vector更有效,因为vector总是会做一个单独的内存分配。你不太可能注意到差异,除非它是在一个大的紧密循环中多次执行的东西。

还是实际上没有那样的东西,我真的不应该再关心数组了?

考虑到C++可以追溯到1983年,从那时起它发生了许多重大变化。现在可用的容器类旨在避免您列出的陷阱,因此它们在这些方面更好也就不足为奇了。但是,您可以使用 C 样式数组执行现代容器类无法执行的一件事:您可以使用非常旧的编译器编译代码。如果你迫切需要保持与 1980 年代中期编译器的兼容性,你应该坚持使用 C 风格的数组。否则,请使用更新、更好的方法。

c-stlye 数组与 stl 容器相比有几个优点(特别是 std::array (。当然,反过来也是如此。

首先,使用 c 样式数组,您可以控制内存布局,这在解释网络数据包或任何类似数据源时非常有用。这允许您将内存块强制转换为结构,从而保存复制/赋值操作,这在某些性能敏感的应用程序中是必需的。

另一个原因是简单 - 如果您不需要 std 容器提供的任何好处,为什么要使用它们?

还有兼容性 - 不同的 stl 实现会随着不同的编译器而改变。在共享库 (so/dll( 的接口中使用数组而不是 stl 容器允许用户使用几乎任何编译器对共享库进行写入。对于 stl 容器,这显然是不正确的。

最后是低级优化。在某些情况下,数组可能比它们的 stl 等效std::array更快,尽管这些情况有些罕见。