数组与向量:介绍性的相似之处和不同之处


111

C ++中的数组和向量之间有什么区别?差异的一个例子可能包括库,符号,能力等。

数组

数组包含特定数量的特定类型的元素。为了使编译器可以在编译程序时保留所需的空间量,必须指定定义数组时数组将包含的元素类型和数量。编译程序时,编译器必须能够确定该值。定义数组后,可以将数组的标识符与索引一起使用,以访问数组的特定元素。数组是零索引的;也就是说,第一个元素在索引0处。此索引方案指示C ++中指针与数组之间的紧密关系以及该语言为指针算术定义的规则。

— C ++ Pocket参考

向量

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

— C ++食谱


最基本的区别:在某些情况下,向量是一个不错的选择。
杰里·科芬

1
“穷举”和“约束”是正交的。就是说,不仅一个意味着另一个,而且它们甚至没有相同的规模。
Lightness Races in Orbit

2
我对那些提出与我所寻找信息完全相同的问题的人感到不安。这种情况经常发生。
罗伯特·坦林

Answers:


142

数组:

  • 是内置的语言构造;
  • 来自C89几乎没有修改;
  • 仅提供一个连续的,可索引的元素序列;没有钟声和口哨声;
  • 大小固定;您无法在C ++中调整数组的大小(除非它是POD数组,并且分配有malloc);
  • 它们的大小必须是编译时常量,除非它们是动态分配的;
  • 它们根据您声明它们的范围来占用它们的存储空间;
  • 如果是动态分配的,则必须显式地取消分配它们;
  • 如果它们是动态分配的,则只会得到一个指针,而无法确定它们的大小;否则,您可以使用sizeof(因此sizeof(arr)/sizeof(*arr),这是通用的习惯用法,但是当在指针上无意使用时,它会无声地失败);
  • 在大多数情况下会自动衰减为指针;特别是在将它们传递给函数时会发生这种情况,通常需要为其大小传递一个单独的参数;
  • 不能从函数返回;
  • 不能直接复制/分配;
  • 动态对象数组需要一个默认的构造函数,因为它们的所有元素都必须首先构造。

std::vector

  • 是模板类;
  • 是仅C ++构造;
  • 被实现为动态数组 ;
  • 动态增长和收缩;
  • 自动管理其内存,销毁后释放该内存;
  • 可以传递给函数或从函数返回(按值);
  • 可以被复制/分配(这将对所有存储的元素进行深层复制);
  • 不会衰减到指针,但是您可以显式获取指向其数据的指针(&vec[0]保证按预期工作);
  • 总是与内部动态数组一起带来其大小(当前存储了多少个元素)和容量(当前分配的块中可以存储多少个元素);
  • 内部动态数组不是在对象本身内部分配的(仅包含一些“簿记”字段),而是由相关模板参数中指定的分配器动态分配的;默认值是从免费存储区(所谓的堆)获取内存,而与实际对象的分配方式无关;
  • 因此,对于小型,短期的本地数组,它们可能不如“常规”数组有效。
  • 重新分配时,对象被复制(在C ++ 11中移动);
  • 不需要默认的构造函数来存储对象;
  • 与其他所谓的STL更好地集成在一起(它提供了begin()/ end()方法,通常的STL typedef,...)

还要考虑数组的“现代替代方案” std::array;我已经在另一个答案中描述了std::vector和之间的区别std::array,您可能需要看看它。


1
谢谢@MatteoItalia。一个或两个参考会很好。
Trancot

1
@Trancot:任何好的C ++书籍都可以。
Matteo Italia

6
@Trancot:我真的不能为您提供更好的参考-这篇文章中突出显示的差异来自Standard的许多不同部分,并且在出色的C ++手册的帮助下可以更好地理解。
Matteo Italia

这样广泛描述的一个例子将是很棒的!
carloswm85

26

我将添加数组在C ++中是非常底层的构造,并且在“学习绳索”时应尽量避免使用它们-甚至Bjarne Stroustrup也建议这样做(他是C ++的设计师)。

向量非常接近与数组相同的性能,但是具有许多便利和安全功能。当与处理原始数组的API接口或构建自己的集合时,您可能会开始使用数组。


1
应用程序接口:(en.wikipedia.org/wiki/API)。它是软件实体(软件包,库,操作系统)入口点的集合。某些API会有入口点,例如strcat(char * dst,char * src),其中dst和src被视为字符数组(即使函数签名暗示了指向字符的指针)。
约翰·卡伦(JohnKällén),

11

这些参考文献几乎回答了您的问题。简而言之,向量的长度是动态的,而数组的大小是固定的。使用数组时,可以在声明时指定其大小:

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);
...

有时您将不知道所需的元素数量,因此矢量对于这种情况非常理想。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.