std::vector中的数据存储是否连续?

3
我有一个字符向量,我想将它的内容作为char*传递给另一个函数:
void foo(boost::shared_ptr<std::vector<boost::uint8_t> > data)
{
    bar(data->size()?reinterpret_cast<char*>(&(data.get()->front())):NULL);
}

我可以假设数据总是以连续的方式存储吗?谢谢。


2
你是指“连续的”吗?是的。 - Nim
1
是的,如果你使用c++11,向量元素是连续的,你还可以使用函数T* data而不是丑陋的强制转换来将底层数组传递给另一个函数。 - pan-
3个回答

6

来自 n2798(C++0x 的草案):

23.2.6 类模板 vector [vector]

1 vector 是支持随机访问迭代器的序列容器。此外,它支持(平摊)常数时间插入和删除操作在末尾; 中间插入和删除需要线性时间。存储管理是自动处理的,但可以提供提示以提高效率。 向量中的元素是连续存储的,这意味着如果 v 是一个类型为 T 而非 bool 的向量,则它遵循恒等式 &v[n] == &v[0] + n 对于所有 0 <= n < v.size()。

还要检查在将元素添加到数组后是否重新分配了内存(从而使任何指针或迭代器无效)。

另请参阅此文章:- Cringe not: Vectors are guaranteed to be contiguous

事实上,连续性实际上是向量抽象的一部分。它非常重要,事实上,当发现 C++98 标准并未完全保证连续性时,C++03 标准被修改以明确添加保证。

还来自C++ FAQ

#include <vector>
#include "Foo.h"  /* get class Foo */

// old-style code that wants an array
void f(Foo* array, unsigned numFoos);

void g()
{
  std::vector<Foo> v;
  ...
  f(v.empty() ? NULL : &v[0], v.size());  ← safe
}

有趣的表达式v.empty() ? NULL : &v[0],如果v为空,则简单地传递NULL指针,否则传递指向v的第一个(零)元素的指针。如果您事先知道v不为空,则可以将其更改为简单的&v[0]。 一般来说,这意味着您保证&v[0]+n == &v[n],其中v是std::vector<T>,n是0 .. v.size()-1范围内的整数。
然而,v.begin()不能保证是T*,这意味着v.begin()不能保证与&v[0]相同:
void g()
{
  std::vector<Foo> v;
  ...
  f(v.begin(), v.size());  ← Error!! Not Guaranteed!!
    ^^^^^^^^^-- cough, choke, gag; not guaranteed to be the same as &v[0]
}

请注意,不等式实际上是 0 <= n <= v.size(),因为您可以读取向量末尾的指针,但不要尝试对其进行解引用。而且,&v[n] 的符号不允许进行解引用。 - Bathsheba

3

来自Cppreference

std::vector是一个封装动态大小数组的序列容器。

元素被连续地存储,这意味着元素不仅可以通过迭代器访问,还可以使用指向元素的常规指针上的偏移量进行访问。

因此,是的,元素在内存中是连续的。这意味着您可以将底层数据容器(使用data()成员函数得到的T[])用作经典数组。


+1,但请注意bool - Bathsheba
@Bathsheba 当然,但是因为OP提到他想要用于一个char的向量... - JBL
@Bathsheba 布尔数据类型有什么问题? - Prince
找到了:https://dev59.com/9rbna4cB1Zd3GeqPWi70 - Prince

0

是的,你可以。标准规定 std::vector 的内存是连续的。但请注意,std::vector<bool> 不是连续的。

实际上,std::vector::data() 会给你一个指向向量第一个元素的指针。你可以使用指针算术运算来访问向量元素。


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