数组 vs 向量:基本相似性和区别介绍

134
在C++中,数组和向量有什么区别?这些区别可能包括所包含的库、符号、能力等。

数组

数组包含特定类型的特定数量的元素。当定义数组时,必须指定数组将包含的元素类型和数量,以便编译器在编译程序时可以保留所需的空间。编译器必须能够在编译程序时确定此值。定义数组后,您可以使用数组标识符和索引来访问数组的特定元素。[...] 数组是以零为基础的;也就是说,第一个元素的索引为0。这种索引方式表明了C++中指针和数组之间的密切关系以及语言定义指针算术规则。

——《C++口袋参考》

向量

一个向量是一个动态大小的对象序列,提供类似数组的operator[]随机访问。成员函数push_back通过复制构造函数将其参数复制,将该副本添加为向量中的最后一个项目,并将其大小增加一。pop_back则完全相反,通过删除最后一个元素来实现。从向量末尾插入或删除项需要平摊常数时间,而从任何其他位置插入或删除需要线性时间。这些是向量的基础知识。在大多数情况下,向量应该是您首选的C样式数组。首先,它们是动态大小的,这意味着它们可以根据需要增长。您不必进行各种研究以确定最佳静态大小,如在C数组的情况下;向量按需增长,如果需要,可以手动调整大小。其次,向量通过at成员函数提供边界检查(但不包括operator[]),因此如果您引用不存在的索引,则可以执行某些操作,而不仅仅是观察程序崩溃或更糟糕地继续执行具有损坏数据的操作。

最基本的不同之处:向量是一个好选择的目的。 - Jerry Coffin
2
“全面”和“简明”是正交的。也就是说,它们不仅不互为蕴含,而且它们甚至不在同一个标度上。 - Lightness Races in Orbit
3个回答

171

数组:

  • 是一种内置的语言构造;
  • 几乎没有从C89中修改;
  • 只提供连续的、可索引的元素序列,没有花哨的功能;
  • 大小固定;你不能在C++中调整数组的大小(除非它是POD数组并使用malloc分配);
  • 它们的大小必须是编译时常数,除非它们是动态分配的;
  • 它们根据你声明它们的范围来占用存储空间;
  • 如果是动态分配的,你必须显式地释放它们;
  • 如果它们是动态分配的,你只会得到一个指针,无法确定它们的大小;否则,你可以使用sizeof(因此通常使用sizeof(arr)/sizeof(*arr)这个习惯用法,在指针上不小心使用时会静默失败);
  • 在大多数情况下自动退化为指针;特别是当将它们传递给函数时,这种情况通常需要传递一个单独的参数来表示它们的大小;
  • 不能从函数返回;(除非是std::array)
  • 不能直接复制/赋值;
  • 对象的动态数组需要一个默认构造函数,因为它们的所有元素必须首先被构造;

std::vector

  • 是一个模板类;
  • 仅在C++中使用;
  • 作为动态数组实现;
  • 可以动态增长和缩小;
  • 自动管理其内存,在销毁时释放;
  • 可以通过值传递给/从函数返回;
  • 可以被复制/赋值(这会对所有存储的元素执行深度复制);
  • 不会衰减为指针,但您可以显式获取它们数据的指针(&vec[0]保证按预期工作);
  • 始终将内部动态数组的大小(当前存储的元素数)和容量(当前分配块中可以存储的元素数)带到一起;
  • 内部动态数组不是在对象本身内分配的(它只包含一些“簿记”字段),而是由相关模板参数中指定的分配器动态分配的;默认值从自由存储区(称为堆)获取内存,与实际对象分配的位置无关;
  • 因此,对于小型、短寿命、本地数组,它们可能比“常规”数组效率低;
  • 重新分配时,对象会被复制(在C++11中移动);
  • 不需要对象的默认构造函数;
  • 与所谓的STL更好地集成(它提供了begin()/end()方法、通常的STL typedef等)。
还要考虑数组的“现代替代品”——std::array;我在另一个答案中已经描述了std::vectorstd::array之间的区别,你可能想看一下。

1
谢谢你,@MatteoItalia。如果能提供一两个参考资料就更好了。 - Trancot
2
@Trancot:任何一本好的C++书都可以。 - Matteo Italia
8
@Trancot:我真的无法给你更好的参考资料了——这篇帖子中强调的差异来自标准的许多不同部分,需要借助一本好的C++手册才能更好地理解。 - Matteo Italia
这样一个详尽的描述的例子会很好! - carloswm85
我相信在C++11中可以返回std::array。 - Meric Ozcan
@MericOzcan:是的,但它们完全是另一回事(如答案结尾所述)。 - Matteo Italia

32
我会添加,数组在C++中是非常低级的构造,当你“学习绳索”时应尽可能避免使用它们 -- 即使是C++的设计者Bjarne Stroustrup也推荐这样做。
向量与数组非常接近,但具有许多方便和安全功能。当你与处理原始数组的API进行交互或构建自己的集合时,你可能会开始使用数组。

1
应用程序接口(API):(http://en.wikipedia.org/wiki/API)。它是软件实体(包、库、操作系统)的入口点集合。一些API将具有类似strcat(char * dst, char * src)的入口点,其中dst和src被视为字符数组(即使函数签名暗示了字符指针)。 - John Källén

17
这些参考资料基本回答了你的问题。简单来说,向量的长度是动态的,而数组的大小是固定的。 使用数组时,在声明时需要指定其大小:
int myArray[100];
myArray[0]=1;
myArray[1]=2;
myArray[2]=3;

对于向量,您只需声明并添加元素。
vector<int> myVector;
myVector.push_back(1);
myVector.push_back(2);
myVector.push_back(3);
...

有时候你不知道需要多少元素,这种情况下使用向量会很理想。

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