简体   繁体   English

为什么std :: deque在默认构造函数中为其元素分配内存?

[英]Why does std::deque allocate memory for its elements in the default constructor?

With g++ 5.4 compiler and GNU standard library libstdc++.so.6, default constructor of std::vector creates an empty container initializing only internal bookkeeping data members on stack. 使用g ++ 5.4编译器和GNU标准库libstdc ++。so.6, std::vector默认构造函数创建一个空容器,仅初始化堆栈上的内部簿记数据成员。 It allocates buffer on heap for data elements later (when the fist element is inserted). 它稍后在堆上为数据元素分配缓冲区(当插入第一个元素时)。 Until recently, I thought it was a common behavior for any standard sequential container with dynamically allocated memory. 直到最近,我认为这是任何具有动态分配内存的标准顺序容器的常见行为。

However, std::deque works differently. 但是, std::deque工作方式不同。 Tracing the following code 跟踪以下代码

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

with ltrace gives 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) +++

_Znwm is an implementation of operator new (please see this ). _Znwmoperator new的实现(请参阅此内容 )。 Considering the internal structure of std::deque and the #define _GLIBCXX_DEQUE_BUF_SIZE 512 line from STL implementation header bits/stl_deque.h , one may conclude that _Znwm(64, 8, 0, 8) allocates std::deque 's map for 8 pointers and _Znwm(512, 128, 0, 128) allocates one chunk of 512 bytes. 考虑到std::deque内部结构和来自STL实现头bits/stl_deque.h#define _GLIBCXX_DEQUE_BUF_SIZE 512行,可以得出结论_Znwm(64, 8, 0, 8)为8分配std::deque的映射。指针和_Znwm(512, 128, 0, 128)分配一个512字节的块。

The question is: what is the reason not to postpone allocating these 512 bytes until the first element in std::deque is inserted? 问题是:在插入std::deque的第一个元素之前,不推迟分配这512个字节的原因是什么?

The most likely reason is that if the implementation did not do, every push_back(), push_front(), begin(), end(), insert() would have to check to see if the block of pointers to pages is allocated, and if not execute allocation of the block of pointers + the first page. 最可能的原因是,如果实现没有这样做,每个push_back(),push_front(),begin(),end(),insert()都必须检查是否分配了指向页面的指针块,并且如果没有执行指针块+第一页的分配。 That conditional checking slows these operations down, and the number of these operations is likely to dwarf the instances of a deque constructor executing. 条件检查会减慢这些操作,并且这些操作的数量可能会使deque构造函数的实例相形见绌。

The implementation has decided to stump up a minimum block of pointers + possibly an empty page. 实现决定了最小的指针块+可能是一个空页面。 Effectively it is like a sentinel. 实际上它就像一个哨兵。

Would you really rather these common member functions be slower? 你真的宁愿这些常见的成员函数更慢吗?

Actually according to the standard (and summarized by cppreference ) the default constructor 实际上根据标准(并通过cppreference汇总 )的默认构造函数

explicit deque( const Allocator& alloc = Allocator() );

Default constructor. 默认构造函数。 Constructs an empty container. 构造一个空容器。

If your particular compiler decided their implementation of the default constructor would allocate some memory, then that was an implementation specific choice to do so. 如果您的特定编译器决定他们的默认构造函数的实现会分配一些内存,那么这是一个特定于实现的选择。

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

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