简体   繁体   English

是否保证std :: vector元素是连续的?

[英]Are std::vector elements guaranteed to be contiguous?

My question is simple: are std::vector elements guaranteed to be contiguous? 我的问题很简单:std :: vector元素是否保证是连续的? In order word, can I use the pointer to the first element of a std::vector as a C-array? 用命令的话,我可以将指向std :: vector的第一个元素的指针用作C数组吗?

If my memory serves me well, the C++ standard did not make such guarantee. 如果我的记忆对我有用,则C ++标准没有做出这样的保证。 However, the std::vector requirements were such that it was virtually impossible to meet them if the elements were not contiguous. 但是,std :: vector要求如此,如果元素不连续,则几乎不可能满足它们。

Can somebody clarify this? 有人可以澄清吗?

Example: 例:

std::vector<int> values;
// ... fill up values

if( !values.empty() )
{
    int *array = &values[0];
    for( int i = 0; i < values.size(); ++i )
    {
        int v = array[i];
        // do something with 'v'
    }
}

This was missed from C++98 standard proper but later added as part of a TR. 适当的C ++ 98标准缺少此功能,但后来将其添加为TR的一部分。 The forthcoming C++0x standard will of course contain this as a requirement. 当然,即将到来的C ++ 0x标准将包含此要求。

From n2798 (draft of C++0x): 从n2798(C ++ 0x草案)起:

23.2.6 Class template vector [vector] 23.2.6类模板向量[vector]

1 A vector is a sequence container that supports random access iterators. 1向量是支持随机访问迭代器的序列容器。 In addition, it supports (amortized) constant time insert and erase operations at the end; 另外,它在末尾支持(摊销)恒定时间插入和擦除操作。 insert and erase in the middle take linear time. 在中间插入和擦除需要线性时间。 Storage management is handled automatically, though hints can be given to improve efficiency. 存储管理是自动处理的,尽管可以提供一些提示以提高效率。 The elements of a vector are stored contiguously, meaning that if v is a vector where T is some type other than bool, then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size(). 向量的元素是连续存储的,这意味着如果v是向量,其中T是非bool的某种类型,则它对所有0 <= n <v都服从&v [n] ==&v [0] + n的标识。尺寸()​​。

As other answers have pointed out, the contents of a vector is guaranteed to be continuous (excepting bool's weirdness). 正如其他答案所指出的那样,向量的内容保证是连续的(布尔的怪异除外)。

The comment that I wanted to add, is that if you do an insertion or a deletion on the vector, which could cause the vector to reallocate it's memory, then you will cause all of your saved pointers and iterators to be invalidated. 我要添加的注释是,如果对向量进行插入或删除,这可能导致向量重新分配其内存,那么您将导致所有保存的指针和迭代器无效。

The standard does in fact guarantee that a vector is continuous in memory and that &a[0] can be passed to a C function that expects an array. 实际上,该标准确实确保了vector在内存中是连续的,并且&a[0]可以传递给需要数组的C函数。

The exception to this rule is vector<bool> which only uses one bit per bool thus although it does have continuous memory it can't be used as a bool* (this is widely considered to be a false optimization and a mistake). 这个规则的例外是vector<bool> ,每个bool仅使用一位,因此尽管它确实具有连续的内存,但不能用作bool* (这被广泛认为是错误的优化和错误)。

BTW, why don't you use iterators? 顺便说一句,为什么不使用迭代器? That's what they're for. 那就是他们的目的。

As other's have already said, vector internally uses a contiguous array of objects. 正如其他人已经说过的, vector内部使用连续的对象数组。 Pointers into that array should be treated as invalid whenever any non-const member function is called IIRC. 每当将任何非常量成员函数称为IIRC时,应将该数组中的指针视为无效。

However, there is an exception!! 但是,有一个例外!

vector<bool> has a specialised implementation designed to save space, so that each bool only uses one bit. vector<bool>具有旨在节省空间的专门实现,因此每个布尔仅使用一位。 The underlying array is not a contiguous array of bool and array arithmetic on vector<bool> doesn't work like vector<T> would. 底层数组不是bool的连续数组,并且vector<bool>上的数组算法无法像vector<T>那样工作。

(I suppose it's also possible that this may be true of any specialisation of vector, since we can always implement a new one. However, std::vector<bool> is the only, err, standard specialisation upon which simple pointer arithmetic won't work.) (我想向量的任何特殊化也可能是正确的,因为我们总是可以实现一个新的std::vector<bool> 。但是, std::vector<bool>是唯一的,错误的,标准的特殊化,简单指针运算将基于此进行。工作。)

I found this thread because I have a use case where vectors using contiguous memory is an advantage. 我找到这个线程是因为我有一个用例,其中使用连续内存的向量是一个优势。

I am learning how to use vertex buffer objects in OpenGL. 我正在学习如何在OpenGL中使用顶点缓冲区对象。 I created a wrapper class to contain the buffer logic, so all I need to do is pass an array of floats and a few config values to create the buffer. 我创建了一个包装器类来包含缓冲区逻辑,因此我要做的就是传递一个浮点数数组和一些配置值来创建缓冲区。 I want to be able to generate a buffer from a function based on user input, so the length is not known at compile time. 我希望能够根据用户输入从函数生成缓冲区,因此在编译时长度未知。 Doing something like this would be the easiest solution: 做这样的事情将是最简单的解决方案:

void generate(std::vector<float> v)
{
  float f = generate_next_float();
  v.push_back(f);
}

Now I can pass the vector's floats as an array to OpenGL's buffer-related functions. 现在,我可以将向量的浮点作为数组传递给OpenGL的与缓冲区相关的函数。 This also removes the need for sizeof to determine the length of the array. 这也消除了使用sizeof确定数组长度的需要。

This is far better than allocating a huge array to store the floats and hoping I made it big enough, or making my own dynamic array with contiguous storage. 这远比分配一个巨大的数组来存储浮点数并希望我做得足够大,或者使自己的动态数组具有连续存储要好得多。

是的,保证std :: vector的元素是连续的。

cplusplus.com: cplusplus.com:

Vector containers are implemented as dynamic arrays; 向量容器被实现为动态数组。 Just as regular arrays, vector containers have their elements stored in contiguous storage locations, which means that their elements can be accessed not only using iterators but also using offsets on regular pointers to elements. 就像常规数组一样,向量容器将其元素存储在连续的存储位置中,这意味着它们的元素不仅可以使用迭代器进行访问,还可以使用元素的常规指针上的偏移量进行访问。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM