C中的 std::vector 和 std::array 有什么区别?什么时候应该优先于另一个?各自的优点和缺点是什么?我的所有教科书都列出了它们是如何相同的 .
std::vector
std::array
std::vector 是一个模板类,它封装存储在堆中的动态数组1,如果添加或删除元素,它将自动增长和收缩 . 它提供了所有钩子( begin() , end() ,迭代器等),使其与STL的其余部分一起工作 . 它还有几个有用的方法,可以让你在普通数组上执行繁琐的操作,例如在向量中间插入元素(它处理在幕后移动后续元素的所有工作) .
begin()
end()
由于它将元素存储在堆上分配的内存中,因此它在静态数组方面有一些开销 .
std::array 是一个模板类,它封装了一个存储在对象本身内的静态大小的数组,这意味着,如果在堆栈上实例化类,则数组本身将在堆栈中 . 它的大小必须在编译时知道(它作为模板参数传递),并且它不能增长或缩小 .
它比 std::vector 更受限制,但它主要是围绕C风格数组的轻量级包装器 . 但是,它更安全,因为禁用了对指针的隐式转换,并且它提供了 std::vector 和其他容器的许多与STL相关的功能,因此您可以轻松地使用STL算法和co . 无论如何,对于固定大小的限制,它比 std::vector 灵活性低得多 .
有关 std::array 的介绍,请查看this article;要快速介绍 std::vector 以及可能的操作,您可能需要查看documentation .
使用 std::vector<T> 类:
std::vector<T>
...与使用内置数组一样快,假设您只执行内置数组允许的事情(读取和写入现有元素) .
...插入新元素时自动调整大小 .
...允许您在向量的开头或中间插入新元素,自动"shifting"其余元素"up"(这有意义吗?) . 它允许您删除 std::vector 中任何位置的元素,自动将其余元素向下移动 .
...允许您使用 at() 方法执行范围检查读取(如果不希望执行此检查,则始终可以使用索引器 [] ) .
at()
[]
使用 std::vector<T> 有两个主要注意事项:
您没有对底层指针的可靠访问权限,如果您正在处理需要数组地址的第三方函数,这可能是一个问题 .
std::vector<bool> 班很傻 . 它实现为压缩的位域,而不是数组 . 如果你想要一个 bool 的数组,请避免使用它!
std::vector<bool>
bool
在使用过程中, std::vector<T> s将比具有相同元素数量的C数组略大 . 这是因为他们需要跟踪少量其他信息,例如他们当前的大小,并且因为只要 std::vector<T> s调整大小,他们就会保留更多的空间 . 这是为了防止他们每次插入新元素时都必须调整大小 . 通过提供自定义 allocator 可以更改此行为,但我从未觉得有必要这样做!
allocator
编辑:在阅读Zud对问题的回复后,我觉得我应该补充一下:
std::array<T> 类与C数组不同 . std::array<T> 是C数组的一个非常薄的包装器,其主要目的是将指针隐藏在类的用户之外(在C中,数组被隐式地转换为指针,通常是令人沮丧的效果) . std::array<T> 类还存储其大小(长度),这可能非常有用 .
std::array<T>
为了强调@MatteoItalia提出的观点,效率差异是数据存储的位置 . 堆内存( vector 需要)需要调用系统来分配内存,如果计算周期,这可能会很昂贵 . 堆栈内存(可能 array )在时间上实际上是"zero-overhead",因为内存是通过调整堆栈指针来分配的,并且在进入函数时只执行一次 . 堆栈还避免了内存碎片 . 可以肯定的是, std::array 并不总是在堆栈中;它取决于你分配它的位置,但与vector相比,它仍然会减少堆中的内存分配 . 如果你有
vector
array
small "array"(在100个元素之下) - (典型的堆栈大约是8MB,所以如果你的代码是递归的,不要在堆栈上分配超过几KB或更少)
大小将被修复
生命周期在函数范围内(或者是与父类具有相同生命周期的成员值)
你在计算周期,
肯定在矢量上使用 std::array . 如果这些要求中的任何一个不成立,则使用 std::vector .
如果您正在考虑使用多维数组,那么std :: array和std :: vector之间还有一个区别 . 多维std :: array将在所有维度中将元素打包在内存中,就像c样式数组一样 . 多维std :: vector不会在所有维度中打包 .
鉴于以下声明:
int cConc[3][5]; std::array<std::array<int, 5>, 3> aConc; int **ptrConc; // initialized to [3][5] via new and destructed via delete std::vector<std::vector<int>> vConc; // initialized to [3][5]
指向c样式数组(cConc)或std :: array(aConc)中第一个元素的指针可以通过向每个前面的元素添加1来遍历整个数组 . 他们紧紧包装 .
指向向量数组(vConc)或指针数组(ptrConc)中第一个元素的指针只能通过前5个(在本例中)元素迭代,然后有12个字节(在我的系统上)用于下一个矢量 .
这意味着初始化为[3] [1000]数组的std :: vector>数组的内存将小于作为[1000] [3]数组初始化的数组,并且内存中的数据都比std更大:数组分配方式 .
这也意味着你不能简单地将一个多维向量(或指针)数组传递给openGL而不考虑内存开销,但是你可以天真地将多维std :: array传递给openGL并让它运行起来 .
向量对数组的优势之一是可以使用 vector_name.size() 找到向量的 current size .
可以想象,这在各种情况下非常有用,您可以轻松地获取array_list中的元素数量 .
向量是容器类,而数组是已分配的内存 .
6 回答
std::vector
是一个模板类,它封装存储在堆中的动态数组1,如果添加或删除元素,它将自动增长和收缩 . 它提供了所有钩子(begin()
,end()
,迭代器等),使其与STL的其余部分一起工作 . 它还有几个有用的方法,可以让你在普通数组上执行繁琐的操作,例如在向量中间插入元素(它处理在幕后移动后续元素的所有工作) .由于它将元素存储在堆上分配的内存中,因此它在静态数组方面有一些开销 .
std::array
是一个模板类,它封装了一个存储在对象本身内的静态大小的数组,这意味着,如果在堆栈上实例化类,则数组本身将在堆栈中 . 它的大小必须在编译时知道(它作为模板参数传递),并且它不能增长或缩小 .它比
std::vector
更受限制,但它主要是围绕C风格数组的轻量级包装器 . 但是,它更安全,因为禁用了对指针的隐式转换,并且它提供了std::vector
和其他容器的许多与STL相关的功能,因此您可以轻松地使用STL算法和co . 无论如何,对于固定大小的限制,它比std::vector
灵活性低得多 .有关
std::array
的介绍,请查看this article;要快速介绍std::vector
以及可能的操作,您可能需要查看documentation .使用
std::vector<T>
类:...与使用内置数组一样快,假设您只执行内置数组允许的事情(读取和写入现有元素) .
...插入新元素时自动调整大小 .
...允许您在向量的开头或中间插入新元素,自动"shifting"其余元素"up"(这有意义吗?) . 它允许您删除
std::vector
中任何位置的元素,自动将其余元素向下移动 ....允许您使用
at()
方法执行范围检查读取(如果不希望执行此检查,则始终可以使用索引器[]
) .使用
std::vector<T>
有两个主要注意事项:您没有对底层指针的可靠访问权限,如果您正在处理需要数组地址的第三方函数,这可能是一个问题 .
std::vector<bool>
班很傻 . 它实现为压缩的位域,而不是数组 . 如果你想要一个bool
的数组,请避免使用它!在使用过程中,
std::vector<T>
s将比具有相同元素数量的C数组略大 . 这是因为他们需要跟踪少量其他信息,例如他们当前的大小,并且因为只要std::vector<T>
s调整大小,他们就会保留更多的空间 . 这是为了防止他们每次插入新元素时都必须调整大小 . 通过提供自定义allocator
可以更改此行为,但我从未觉得有必要这样做!编辑:在阅读Zud对问题的回复后,我觉得我应该补充一下:
std::array<T>
类与C数组不同 .std::array<T>
是C数组的一个非常薄的包装器,其主要目的是将指针隐藏在类的用户之外(在C中,数组被隐式地转换为指针,通常是令人沮丧的效果) .std::array<T>
类还存储其大小(长度),这可能非常有用 .为了强调@MatteoItalia提出的观点,效率差异是数据存储的位置 . 堆内存(
vector
需要)需要调用系统来分配内存,如果计算周期,这可能会很昂贵 . 堆栈内存(可能array
)在时间上实际上是"zero-overhead",因为内存是通过调整堆栈指针来分配的,并且在进入函数时只执行一次 . 堆栈还避免了内存碎片 . 可以肯定的是,std::array
并不总是在堆栈中;它取决于你分配它的位置,但与vector相比,它仍然会减少堆中的内存分配 . 如果你有small "array"(在100个元素之下) - (典型的堆栈大约是8MB,所以如果你的代码是递归的,不要在堆栈上分配超过几KB或更少)
大小将被修复
生命周期在函数范围内(或者是与父类具有相同生命周期的成员值)
你在计算周期,
肯定在矢量上使用
std::array
. 如果这些要求中的任何一个不成立,则使用std::vector
.如果您正在考虑使用多维数组,那么std :: array和std :: vector之间还有一个区别 . 多维std :: array将在所有维度中将元素打包在内存中,就像c样式数组一样 . 多维std :: vector不会在所有维度中打包 .
鉴于以下声明:
指向c样式数组(cConc)或std :: array(aConc)中第一个元素的指针可以通过向每个前面的元素添加1来遍历整个数组 . 他们紧紧包装 .
指向向量数组(vConc)或指针数组(ptrConc)中第一个元素的指针只能通过前5个(在本例中)元素迭代,然后有12个字节(在我的系统上)用于下一个矢量 .
这意味着初始化为[3] [1000]数组的std :: vector>数组的内存将小于作为[1000] [3]数组初始化的数组,并且内存中的数据都比std更大:数组分配方式 .
这也意味着你不能简单地将一个多维向量(或指针)数组传递给openGL而不考虑内存开销,但是你可以天真地将多维std :: array传递给openGL并让它运行起来 .
向量对数组的优势之一是可以使用 vector_name.size() 找到向量的 current size .
可以想象,这在各种情况下非常有用,您可以轻松地获取array_list中的元素数量 .
向量是容器类,而数组是已分配的内存 .