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. 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. Tracing the following code
#include <deque>
int main() {
std::deque<int> d;
return 0;
}
with ltrace
gives
__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).
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.
The question is: what is the reason not to postpone allocating these 512 bytes until the first element in std::deque
is inserted?
A constructor does not allocate memory for the class object its this pointer refers to, but may allocate storage for more objects than its class object refers to. If memory allocation is required for objects, constructors can explicitly call the new operator.
The size of the problem often can not be determined at “compile time”. Dynamic memory allocation is to allocate memory at “run time”. Dynamically allocated memory must be referred to by pointers. the computer memory which can be accessed by the identifier (the name of the variable).
The standard contiguous-memory containers are vector, string, and deque.
The math behind them not withstanding, std::deque has random access iterators, and as such any in-place sorting algorithm will be able to sort the data within using that functionality and not requiring O(N) additional storage. std::list doesn't provide random access iteration, and thus is not std::sort -able.
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. That conditional checking slows these operations down, and the number of these operations is likely to dwarf the instances of a deque constructor executing.
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With