在 vector::push_back 内存的背后会发生什么?

发布于 2024-12-12 03:31:11 字数 271 浏览 0 评论 0原文

我的问题是关于 vector::push_back 的效果,我知道它在向量的末尾添加了一个元素,但是在引擎盖下会发生什么?

IIRC 内存对象是以顺序方式分配的,所以我的问题是 vector::push_back 是否只是在向量之后立即分配更多内存,如果是这样,如果该位置没有足够的可用内存会发生什么?或者也许在“末尾”添加一个指针以使向量“跳跃”到它继续的位置?或者只是通过将其复制到另一个有足够空间的位置来重新分配,并且旧副本被丢弃?或者也许是别的什么?

My question is regarding the effect of vector::push_back, I know it adds an element in the end of the vector but what happens underneath the hood?

IIRC memory objects are allocated in a sequential manner, so my question is whether vector::push_back simply allocates more memory immediately after the vector, and if so what happens if there is not enough free memory in that location? Or perhaps a pointer is added in the "end" to cause the vector to "hop" to the location it continues? Or is it simply reallocated through copying it to another location that has enough space and the old copy gets discarded? Or maybe something else?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

无尽的现实 2024-12-19 03:31:11

如果已经分配了足够的空间,则该对象是从就地参数复制构造的。当没有足够的内存时,向量将按照某种几何级数增长其内部数据缓冲区(每次新大小将为k*old_size,其中k > 1 [1]),并且原始缓冲区中存在的所有对象将移动到新缓冲区。操作完成后,旧缓冲区将被释放给系统。

在上一句中,move 没有在技术move-constructor/ move-assignment 意义上使用,它们可以移动 em> 或复制 或任何等效操作。

[1] 增长一个因子 k > 1 确保 push_back 的摊余成本恒定。实际常量因一种实现而异(Dinkumware 使用 1.5,gcc 使用 2)。摊余成本意味着,即使每隔一段时间一次 push_back 都会非常昂贵(O(N) 取决于当时向量的大小),但这些情况很少发生足以使整个插入集上的所有操作的成本与插入数量呈线性关系,因此每个插入平均恒定成本)

If there is enough space already allocated, the object is copy constructed from the argument in place. When there is not enough memory, the vector will grow it's internal databuffer following some kind of geometric progression (each time the new size will be k*old_size with k > 1[1]) and all objects present in the original buffer will then be moved to the new buffer. After the operation completes the old buffer will be released to the system.

In the previous sentence move is not used in the technical move-constructor/ move-assignment sense, they could be moved or copied or any equivalent operation.

[1] Growing by a factor k > 1 ensures that the amortized cost of push_back is constant. The actual constant varies from one implementation to another (Dinkumware uses 1.5, gcc uses 2). The amortized cost means that even if every so often one push_back will be highly expensive (O(N) on the size of the vector at the time), those cases happen rarely enough that the cost of all operations over the whole set of insertions is linear in the number of insertions, and thus each insertion averages a constant cost)

苏辞 2024-12-19 03:31:11

当向量空间不足时,它将使用其分配器来保留更多空间。

由分配器决定如何实现。

然而,向量决定了要保留多少空间:该标准保证向量容量应以几何方式增长至少 1.51 倍(参见注释),从而防止由于重复的“小”分配而导致糟糕的性能。

关于元素的物理移动/复制:

  • 如果支持移动分配和构造,符合 c++11 的实现将移动元素,
  • 我知道的大多数实现(尤其是 g++)将仅使用 std::copy 进行 POD类型; POD 类型的算法专门化确保它编译成(本质上)memcpy 操作。这反过来会被编译成系统上最快的任何 CPU 指令(例如 SSE2 指令)

1 我尝试从 n3242 标准草案文档中找到该指令的参考引用,但我无法在这次

When vector is out of space, it will use it's allocator to reserve more space.

It is up to the allocator to decide how this is implemented.

However, the vector decides how much space to reserve: the standard guarantees that the vector capacity shall grow by at least a factor of 1.51 geometrically (see comment), thus preventing horrible performance due to repeated 'small' allocations.

On the physical move/copy of elements:

  • c++11 conforming implementations will move elements if they support move assignment and construction
  • most implementations I know of (g++ notably) will just use std::copy for POD types; the algorithm specialisation for POD types ensures that this compiles into (essentially) a memcpy operation. This in turn gets compiled in whatever CPU instruction is fastest on your system (e.g. SSE2 instructions)

1 I tried finding the reference quote for that from the n3242 standard draft document, but I was unable to find it at this time

听风吹 2024-12-19 03:31:11

向量保证所有元素在内存中都是连续的。

在内部,您可以将其视为定义为三个指针(或类似指针的行为):

start:     Points at the beginning of the allocated block.
final:     Points one past the last element in the vector.
           If the vector is empty then start == final 
capacity:  Points one past the end of allocated memory.
           If final == capacity there is no room left.

当您向后推时。

  1. 如果最终值小于容量:
    • 新元素被复制到final指向的位置
    • final 递增到下一个位置。
  2. 如果最终与容量相同,则向量已满
    • 必须分配新内存。
    • 编译器随后将分配 X*(capacity - start)*sizeof(t) 字节。
    • 其中 X 通常是 1.5 到 2 之间的值。
    • 然后,它将所有值从旧内存缓冲区复制到新内存缓冲区。
    • 新值将添加到缓冲区中。
    • 传输开始/最终/容量指针。
    • 释放旧缓冲区

A vector gurantees that all elements are contigious in memory.

Internally you can think of it as defined as three pointers (or what act like pointers):

start:     Points at the beginning of the allocated block.
final:     Points one past the last element in the vector.
           If the vector is empty then start == final 
capacity:  Points one past the end of allocated memory.
           If final == capacity there is no room left.

When you push back.

  1. If final is smaller than capacity:
    • the new element is copied into the location pointed at by final
    • final is incremented to the next location.
  2. If final is the same as capacity then the vector is full
    • new memory must be allocated.
    • The compiler will then allocate X*(capacity - start)*sizeof(t) bytes.
    • where X is usually a value between 1.5 and 2.
    • It then copies all the values from the old memory buffer to the new memory buffer.
    • the new value is added to the buffer.
    • Transfers start/final/capacity pointers.
    • Free's up the old buffer
二货你真萌 2024-12-19 03:31:11

vector空间不足时,它会被重新分配,所有元素都会被复制到新数组中。然后旧的数组被销毁。

为了避免过多的分配并将平均 push_back() 时间保持在 O(1),重新分配要求大小至少增加一个常数因子。 (1.5和2是常见的)

When vector runs out of space, it is reallocated and all the elements are copied over to the new array. The old array is then destroyed.

To avoid an excessive number of allocations and to keep the average push_back() time at O(1), a reallocation requires that the size be increased by at least a constant factor. (1.5 and 2 are common)

盗心人 2024-12-19 03:31:11

如果您知道数组的最终大小是多少,请首先尝试 vector::reserve 内存。请注意,reservevector::resize 不同。使用 reserve 时,数组的 vector::size() 不会更改

If you have some idea of what will be the final size of your array, try to vector::reserve the memory first. Note that reserve is different from vector::resize. With reserve the vector::size() of your array is not changed

醉殇 2024-12-19 03:31:11

当您调用vector::push_back时,end指针将与capacity指针进行比较。如果有足够的空间容纳新对象,则会调用 placement new 在可用空间中构造对象,并且 end 指针会递增。

如果没有足够的空间,vector 会调用其分配器 为至少现有元素和新元素分配足够的连续空间(不同的实现可能会以不同的方式增加分配的内存)乘数)。然后所有现有元素加上新元素都会复制到新分配的空间中。

When you call vector::push_back the end pointer is compared to the capacity pointer. If there is enough room for the new object placement new is called to construct the object in the available space and the end pointer is incremented.

If there isn't enough room the vector calls its allocator to allocate enough contiguous space for at least the existing elements plus new element (different implementation may grow the allocated memory by different multipliers). Then all existing elements plus the new one are copied to the newly allocated space.

又怨 2024-12-19 03:31:11

std::vector 过度分配 - 它通常会自动分配比所需更多的内存。 size不受此影响,但您可以通过capacity进行控制。

如果额外容量不够,std::vector 将复制所有内容

std::vector 分配的内存是原始的,没有按需调用构造函数,使用放置 new。

所以,push_back 的作用是:

  • 如果容量不足以容纳新元素,它将
    • 分配一个新块
    • 复制所有现有元素(通常使用复制构造函数)
  • 将大小增加一个
  • 将新元素复制到新位置

std::vector overallocates - it will usually allocate more memory than necessary automatically. sizeis not affectd by this, but you can control that through capacity.

std::vector will copy everything if the additional capacity is not sufficient.

The memory allocated by std::vector is raw, no constructors are called on demand, using placement new.

So, push_back does:

  • if capacity is not sufficient for the new element, it will
    • allocate a new block
    • copy all existing elements (usually using the copy constructor)
  • increase size by one
  • copy the new element to the new location
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文