简体   繁体   English

为什么不能保证向量的向量是连续的? (或者是?)

[英]Why isn't a vector of a vector guaranteed to be contiguous? (or is it?)

I know std::vector elements are guaranteed contiguous in memory. 我知道std::vector元素在内存中保证是连续的。

So then why can't you expect a vector containing other vectors to have the total collection contiguous? 那么,为什么不能期望包含其他向量的向量具有连续的总集合呢?

The vector is supposed to guarantee contiguous memory layout for its enclosed items, and if those enclosures are also vectors, then I'd expect the full contents of the top-most vector to be in contiguous memory. 向量应该保证其封闭项目的连续内存布局,如果这些封闭空间也是向量,那么我希望最顶层向量的完整内容位于连续内存中。

But there seems to be some contention on this issue as to whether or not this is true. 但是,在这个问题上似乎存在一些争议,那就是这是否成立。 Can one safely rely on it or not? 可以安全地依靠它吗? Some folks seem to go out of their way to achieve this, while I'd think it is guaranteed. 有些人似乎竭尽全力实现这一目标,而我认为这是可以保证的。

Each of your vector inside the vector of vectors is an individual object, and as such is responsible for it's storage. 向量中的每个向量都是一个单独的对象,因此负责存储。 So, no, it is by no means guaranteed to be contiguous, in fact I can 't really see a situation where it could happen that the data stored in the outer vector and it's inner vectors is one contiguous block of memory ever. 因此,不,它绝不能保证是连续的,实际上我看不到一种情况,即存储在外部向量及其内部向量中的数据永远是一个连续的内存块。

I think the most correct formal way of answering this (as opposed to describing existing implementations) is based on §23.3.6.1/1: 我认为回答这个问题的最正确的正式方式(与描述现有实现相反)是基于§23.3.6.1/ 1:

[...] The elements of a vector are stored contiguously, meaning that if v is a vector<T, Allocator> where T is some type other than bool, then it obeys the identity [...]向量的元素是连续存储的,这意味着如果vvector<T, Allocator> ,其中T是布尔值以外的其他类型,则它服从同一性

 &v[n] == &v[0] + n 

for all 0 <= n < v.size() . 对于所有0 <= n < v.size()

Note that this talks about the addresses &v[i] of individual elements of the vector and implies, in particular, that each element of the vector has constant size sizeof(T) (because that's how pointer arithmetic works). 请注意,这是关于向量的各个元素的地址&v[i]的,尤其是暗示向量的每个元素的大小为sizeof(T)不变(因为这是指针算术的工作方式)。

This means it is impossible for the elements of a vector to change size at run-time. 这意味着向量的元素在运行时无法更改大小。 If a vector<vector<T>> was implemented as one contiguous block of memory, the members of the outer vector, being themselves vectors, would be allowed to change size. 如果将vector<vector<T>>实现为一个连续的内存块,则允许外部矢量(本身是矢量)的成员更改大小。

Therefore, there must be an extra level of indirection, ie, the individual vectors must contain some sort of pointer to a variable-size data structure stored at a different place. 因此,必须有一个额外的间接级别,即,各个向量必须包含某种指向存储在不同位置的可变大小数据结构的指针。

A vector is an object containing a pointer to the actual array. 向量是一个包含指向实际数组的指针的对象。

A vector of vectors would be an object with a pointer to an array of objects, each of which points to its own array elsewhere on the heap. 向量的向量将是一个对象,该对象具有指向对象数组的指针,每个对象都指向堆上其他位置的数组。 So no, they would never be contiguous in the way that you're asking. 因此,不,它们永远不会按照您的要求是连续的。

Let's look at the (logical) memory layout of vector: 让我们看一下向量的(逻辑)内存布局:

[size:4/8 bytes]
[capacity:4/8 bytes]
[other datamembers:n bytes]
*[elements:size*sizeof(element) bytes] << one contiguous memory (pointer to heap)

With a vector of vectors it looks like this: 通过向量向量,它看起来像这样:

[size:4/8 bytes]
[capacity:4/8 bytes]
[other datamembers:n bytes]
* [
    [Vector:0]
        [size:4/8 bytes]
        [capacity:4/8 bytes]
        [other datamembers:n bytes]
        *[elements:size*sizeof(element) bytes] << pointer to contiguous memory for elements
    [Vector:1]
        [size:4/8 bytes]
        [capacity:4/8 bytes]
        [other datamembers:n bytes]
        *[elements:size*sizeof(element) bytes]
    [Vector:2]
        [size:4/8 bytes]
        [capacity:4/8 bytes]
        [other datamembers:n bytes]
        *[elements:size*sizeof(element) bytes]
    ...
    ...
] << contiguous memory of vectors

This means that a vector has a pointer to contiguous memory storing vectors, each of which stores their elements pointing to another heap with contiguous memory storing the elements. 这意味着一个向量具有一个指向连续存储器存储向量的指针,每个向量都存储其指向另一个堆的元素,而连续存储器存储这些元素。

But if you managed to create an allocator to be used by the vector, such that it would allocate blocks of memory that are contiguous, you'd still face issues where if one of the nested vectors gets removed, the memory is no longer contiguous. 但是,如果您设法创建了一个可被向量使用的分配器,从而可以分配连续的内存块,那么您仍然会遇到以下问题:如果删除了一个嵌套向量,则该内存将不再是连续的。 Not to mention the situation of having the nested vector having different sizes. 更不用说使嵌套向量具有不同大小的情况。

Depending on your use-case you can either use the customer contiguous block memory allocator for a vector of vector, or just do it the old way of manually allocating and deallocating one contiguous block of memory. 根据您的用例,您可以将客户连续块内存分配器用作向量的向量,或者仅使用手动分配和取消分配一个连续内存块的旧方法。

The problem is that the vector template doesn't contain the data it handle "inline", or directly. 问题在于矢量模板不包含它“内联”或直接处理的数据。 Another way of saying it that the vector class boxes the data array it holds: the vector class holds a pointer to the memory area containing the array of elements. 换句话说,向量类将其持有的数据数组装箱:向量类持有指向包含元素数组的存储区的指针。 It is structurally equivalent to: 它在结构上等同于:

template <typename T>
struct vector_eq {
    T *ptr;
};

and not 并不是

template <typename T>
struct vector_neq {
    T arr[SIZE];
};

which would require SIZE to be known at compile time (ie. a constexpr ), for arr elements to be included in the struct. 这要求在编译时知道SIZE (即constexpr ),以便将arr元素包括在结构中。

I imagine thar it should be possible to specialise vector<vector<T>> to contain a pointer to a single block of memory, and have its methods return ad hoc instances of vector<T> sharing slices of that memory block, although the logic behind it would probably be a bit hairy. 我想有可能专门化vector<vector<T>>来包含指向单个内存块的指针,并使它的方法返回vector<T>临时实例,共享该内存块的切片,尽管逻辑后面可能有点毛。

To put it simply - std::vector guarantees the elements are stored contiguously. 简而言之-std :: vector确保元素连续存储。 But that only includes the element's member data, in the case of vector that would be its size, capacity and stuff like that, plus the pointer to the actual vector data. 但是,在向量的情况下,它仅包括元素的成员数据,这将是其大小,容量和类似的东西,再加上指向实际向量数据的指针。

So, a vector of vectors will give you a contiguous vector of vectors, but those vectors will have their data dynamically allocated on arbitrary memory addresses. 因此,向量向量将为您提供向量的连续向量,但这些向量将在任意存储器地址上动态分配其数据。

Since an object size needs to be known at compile time, you cannot have objects with varying size, the only way to do this is to use dynamic memory allocation. 由于需要在编译时知道对象的大小,因此您不能拥有大小不同的对象,唯一的方法是使用动态内存分配。 If you had a custom vector of fixed size that uses no dynamic memory allocation internally, then a std::vector<customVector> would store the customVectors contiguously, but you will still have the additional auxiliary members which will "interrupt" the actual contiguity of the customVector element data. 如果您有一个固定大小的自定义向量,该向量在内部不使用动态内存分配,则std::vector<customVector>将连续存储customVector,但是您仍将拥有其他辅助成员,这些成员将“中断”该对象的实际连续性customVector元素数据。

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

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