【问题标题】:Why does std::deque allocate memory for its elements in the default constructor?为什么 std::deque 在默认构造函数中为其元素分配内存?
【发布时间】:2016-10-24 05:42:07
【问题描述】:

使用 g++ 5.4 编译器和 GNU 标准库 libstdc++.so.6,std::vector 的默认构造函数创建一个空容器,仅初始化堆栈上的内部簿记数据成员。它稍后在堆上为数据元素分配缓冲区(当插入第一个元素时)。直到最近,我还认为这是任何具有动态分配内存的标准顺序容器的常见行为。

但是,std::deque 的工作方式不同。跟踪以下代码

#include <deque> 
int main() {
    std::deque<int> d;
    return 0;
}

ltrace 给予

__libc_start_main(0x4024fa, 1, 0x7ffd088be0f8, 0x405bd0 <unfinished ...>
_ZNSt8ios_base4InitC1Ev(0x608351, 0xffff, 0x7ffd088be108, 160)        = 0
__cxa_atexit(0x401f20, 0x608351, 0x608210, 0x7ffd088bded0)            = 0
_Znwm(64, 8, 0, 8)                                                    = 0x7b4c20
_Znwm(512, 128, 0, 128)                                               = 0x7b4c70
_ZdlPv(0x7b4c70, 0x7b4c70, 128, 0x7b4c70)                             = 1
_ZdlPv(0x7b4c20, 0x7b4c20, 8, 0x7b4c20)                               = 0
_ZNSt8ios_base4InitD1Ev(0x608351, 0, 0x401f20, 0x7fc6d4567d10)        = 0x7fc6d4b00880
+++ exited (status 0) +++

_Znwmoperator new 的实现(请参阅this)。 考虑到 STL 实现头 bits/stl_deque.h 中的 internal structure of std::deque#define _GLIBCXX_DEQUE_BUF_SIZE 512 行,可以得出结论,_Znwm(64, 8, 0, 8) 为 8 个指针分配了 std::deque 的映射,_Znwm(512, 128, 0, 128) 分配了 512 字节的一块。

问题是:为什么不推迟分配这 512 个字节,直到插入 std::deque 中的第一个元素?

【问题讨论】:

  • 你确定你的主要陈述按照 C++ 标准是正确的吗?
  • 我具体描述了我的实现。
  • 也许您可以将该信息添加到您的问题中。
  • 在问题的开头添加了请求的信息。
  • 我认为推迟内存分配也有利有弊。如果内存分配被推迟到第一个元素被插入,那么这意味着如果在关键路径中有插入,则无法避免内存分配中引入的延迟,因为deque::reserve() 不存在(而vector::reserve() 存在) .但是如果在构造deque的时候就完成了初始内存分配,程序员可以在关键路径之外创建deque

标签: c++


【解决方案1】:

最可能的原因是,如果实现没有这样做,每个 push_back()、push_front()、begin()、end()、insert() 都必须检查指向页面的指针块是否分配,如果没有执行指针块+第一页的分配。条件检查会减慢这些操作的速度,并且这些操作的数量可能会使执行的双端队列构造函数的实例相形见绌。

实现已决定建立一个最小的指针块 + 可能是一个空页面。实际上它就像一个哨兵。

您真的希望这些常见的成员函数更慢吗?

【讨论】:

  • 无论如何,push_back() 和您提到的其他成员函数必须检查相应的块(术语中的页面)是否有空闲空间来放置要添加的元素并在必要时分配另一个块。从我的角度来看,检查本身并不会显着减慢成员函数的速度。它是分配的内存。假设我们无法避免在提到的成员函数中分配内存,再添加一个不会显着改变这种情况。如果我错了,请纠正我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-09
  • 2022-01-04
  • 2020-03-24
  • 1970-01-01
  • 1970-01-01
  • 2017-01-10
  • 1970-01-01
相关资源
最近更新 更多