std::array和std::vector有什么区别?在何时使用其中之一?

121

std::arraystd::vector有什么区别?在什么情况下使用其中一种?

我一直认为std::vector是C++中使用C数组的方法,所以它们之间有什么区别呢?

6个回答

163

std::array是经典的C数组的类版本。这意味着其大小在编译时固定,并且将作为单个块分配(例如占用堆栈空间)。它的优点是性能略好,因为对象和数组数据之间没有间接引用。

std::vector是一个小型类,包含指向堆的指针。(因此,当您分配std::vector时,它总是调用new。)它们访问速度稍慢,因为那些指针必须追踪以获取数组化数据...但作为交换,它们可以被重设大小,并且无论它们有多大,它们只会占据微不足道的堆栈空间。

[编辑]

至于何时使用其中之一,老实说,std::vector几乎总是您想要的。通常不建议在堆栈上创建大型对象,并且额外的间接级别通常是无关紧要的。(例如,如果您遍历所有元素,则额外的内存访问仅在循环开始时发生一次。)

向量的元素保证是连续的,因此您可以将&vec[0]传递给任何期望指向数组的指针的函数;例如C库例程。 (顺便说一句,std::vector<char> buf(8192);是为调用read/write等而分配本地缓冲区的绝佳方法,而无需直接调用new。)

也就是说,在需要经常创建/销毁/访问的非常小的数组时,那个额外的间接级别加上编译时常量大小可以使std::array显着更快。

所以我的建议是:使用std::vector,除非(a)您的分析器告诉您存在问题并且(b)数组很小。


1
等等,什么开销?两者都通过“指针”进行间接引用。在std::array的情况下,“指针”只是伪装成一个T arr[N]; - Xeo
12
@Xeo:那不是一个指针,而是一个数组。它实际上是在对象内部; 不是由对象指向的。如果您查看生成的汇编代码,您会发现访问向量元素比访问数组多一个内存访问。 (尽管在实践中通常是无关紧要的;例如,循环遍历向量只在循环开始时执行额外的间接引用一次。) - Nemo
6
并不完全正确:std::vector的数据存储在单独分配的内存中,而std::array的数据则不是。 (当你需要时,哪里有评论的-1按钮?) - C. K. Young
1
+1,但我要指出,“面向对象”可能会误导……std::array不一定包含对象(std::vector也是如此)。 - Caleb
1
@CharlesBailey,我认为我们并没有产生分歧,只是在使用“对象”的两种不同方式。《C++程序设计语言》的第4.9.6节将对象称为“内存中的某些东西”,我认为这就是你使用该词的方式。我倾向于认为“对象”意味着“类的实例”,我认为这在“面向对象”中是强烈暗示的。例如,第2.6节,标题为“面向对象编程”,专门讨论了类。这就是为什么我认为将“面向对象”这个短语应用于std::vector可能会产生误导的原因。 - Caleb
显示剩余9条评论

22

我假设您知道std::array是编译时固定大小的,而std::vector是可变大小的。另外,我假设您知道std::array不进行动态分配。因此,我将回答为什么您会使用std::array而不是std::vector。

您是否曾经发现自己这样做:

std::vector<SomeType> vecName(10);

那么你从未实际增加std::vector的大小吗?如果是这样,那么std::array是一个很好的替代品。

但实际上,std::array(与初始化列表配合使用)存在的意义在于几乎完全淘汰C风格数组。它们通常不与std::vectors竞争;它们更多地与C风格数组竞争。

把它看作是C++委员会尽力消除几乎所有合法使用C风格数组的方法。


14

std::array

  • 是一个聚合体
  • 是固定大小的
  • 要求其元素可默认构造(与C++03中的复制或C++0x中的移动构造不同)
  • 是线性交换的(与常数时间不同)
  • 是线性可移动的(与常数时间不同)
  • std::vector可能少支付一个间接寻址

当需要做一些“接近底层”的事情,同时保持C++的良好特性并将所有原始数组的问题绕开时,使用std::array是一个很好的选择。


9

当使用C风格的静态数组时,与使用std::vector相同的原理。关于这一点,我友好地向您推荐这里


我必须说,我认为我的答案比任何一个答案都好。但也许是我有点困了。 - Nemo
@Nemo:我同意你的答案更好,如果你能简要总结一下何时使用其中之一,那就更完整了。 - Alok Save

8

std::array 是一个固定大小(在编译时确定)的数组,而 std::vector 可以动态增长。

因此,使用 std::array 就像使用 C 数组,而使用 std::vector 就像动态分配内存。


1
这对于嵌入式世界非常重要。在我的环境中,我没有堆,也不允许动态内存分配。我们只有栈。因此,禁止使用向量。std::array对我们很好。谢谢。 - Mehmet Fide
@MehmetFide 我很好奇那是什么样的环境 :) - Floella

2

我使用自己编写的Array<>模板类,与std::arraystd::vector相比,它具有更简单的API。例如:

要使用动态数组:

Array<>  myDynamicArray; // Note array size is not given at compile time
myDynamicArray.resize(N); // N is a run time value

...

要使用静态数组,在编译时固定大小:

Array<100> myFixedArry;

我相信它的语法比std::arraystd::vector更好。而且非常高效。


能否把那个 Array<> 模板发一下? - Zimano

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