std::allocator

hey guys I had a thread that uses the same code not so long ago,this code is a strong example of what I'm trying to ask so I'll re-use it.

I have done some research but still have a few questions as things don't seem clear

so first off why does std::allocate have two functions that seem to do the same thing? deallocate and destroy,from what I read in c++ the creation of objects behind the scenes,first calls malloc which allocates enough memory for the object(s)you want,then new creates that object,

but that still leaves the question why would we need both destroy and deallocate aswell as allocate and construct? When calling the new keyword malloc gets executed d first then the object is created in that memory,so if this gets taken care of with the new keyword why would we need two functions (allocate and construct) why couldn't we just have a function called construct that calls the new keyword

and have a function destroy that frees and deletes the object which the delete keyword does

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183


#include <iostream>

using namespace std;

template <class T,class A = allocator<T> > class Vector{

  A alloc;
  int size;
  int space;
  T *elem;

  public:
      Vector(int size)
      : size(size),elem(new T[size])
      {

        space = size;
        for(int i = 0; i < size; i++){

            elem[i] = 0;
        }
      }

      Vector(){

         size = 0;
         elem = 0;
         space = 0;

      }

      Vector(const Vector& other)
      {

        size = other.size;
        elem = new T[other.size];
        copyValues(other);
      }

      void copyValues(const Vector& other){

         for(int i = 0; i < size; i++){

            elem[i] = other.elem[i];
         }
      }

      Vector& operator=(const Vector& other){

         T *p = new T[other.size];

         for(int i = 0; i < other.size; i++){

            p[i] = other.elem[i];
         }
         delete[] elem;
         elem = p;
         size = other.size;
         return *this;
      }

      T& operator[](int i){

         return elem[i];
      }

       T operator[](int i)const{

         return elem[i];
      }

      int vectorSize(){

       return size;
      }

      void reserve(int amount){

         if(amount <= space){
            return;
         }
         T *p = alloc.allocate(amount);
         for(int i = 0; i < size; i++){

            alloc.construct(&p[i],elem[i]);
         }
          for(int i = 0; i < size; i++){

            alloc.destroy(&elem[i]);
         }

         alloc.deallocate(elem,space);

         elem = p;
         space = amount;
      }

      void resize(int newSize,T val = T()){

         reserve(newSize);
         for(int i = size; i < newSize; i++){

            alloc.construct(&elem[i],val);
         }
         for(int i = newSize; i < size; i++){

            alloc.destroy(&elem[i]);
         }
         size = newSize;
      }

      void push_back(const T& val){

           if(space == 0){

            reserve(8);
           }
           if(size == space){

            reserve(2 * space);
           }
           alloc.construct(&elem[size],val);
           size++;

      }

};

class hey{

  public:
      int a;
      int b;

      hey(){

       a = 7;
       b = 7;
      }
      hey(int x,int y){

       a = x;
       b = y;

      }
      hey(const hey& other){

       a = other.a;
       b = other.b;

      }

      hey& operator=(const hey& other){


       a = other.a;
       b = other.b;
       return (*this);
      }

};

int main()
{
   Vector<hey> sample;
   hey h(5,3);
   hey b(7,3);
   hey c(8,2);
   sample.push_back(h);
   sample.push_back(b);
   sample.push_back(c);

   sample[0].a = 9;

   for(int i = 0; i < sample.vectorSize(); i++){

      cout << sample[i].a << endl;
   }
}



also in the resize function why do we only call destroy but not deallocate?

and in the reserve function we call both destroy and deallocate?

thanks guys
adam2016 wrote:
why couldn't we just have a function called construct that calls the new keyword and have a function destroy that frees and deletes the object which the delete keyword does

because the new keyword and the delete keyword each do two different things. Allocators exist to customize as much as possible, and each allocator has five customization points: allocation, construction, addressing, destruction, and deallocation.

Most users only customize allocation and deallocation and leave construct/destroy/pointer alone. Pointer customization is less common, but still happens in real life (e.g. for shared-memory allocators), and there are only obscure situations where you may wish to customize construction/destruction.

One example I know is for std::vectors of primitive types: they zero themselves out on construction and resize. If you create a vector for use as a buffer where you plan to write values first, before reading them, that zeroing out on construction is a waste of time, and you can customize the allocator::construct to skip it.

PS: your demo Vector is not using allocators properly: as of C++11, they must always be accessed through std::allocator_traits, otherwise you can't use other people's C++11 allocators
Last edited on

because the new keyword and the delete keyword each do two different things. Allocators exist to customize as much as possible, and each allocator has five customization points: allocation, construction, addressing, destruction, and deallocation.



but internally what is the difference between creating (construction ) and allocating( allocate) and also freeing the memory( deallocate ) and destroying the memory (destruct)?

also in the resize function why do we only call destroy but not deallocate?

and also in the reserve function we call both destroy and deallocate?


thanks Cubbi :)
Last edited on
internally what is the difference between creating (construction ) and allocating( allocate) and also freeing the memory( deallocate ) and destroying the memory (destruct)?

allocate obtains raw memory, construct creates objects in it (executes constructors), destroy kills those objects (executes destructors), deallocate returns the raw memory to wherever it came from.

In a vector, specifically, memory between data+size and data+capacity is allocated, but not filled with objects: construct was either never called on it or was followed by destroy.

in the resize function why do we only call destroy but not deallocate?

vector::resize never reduces capacity, it can only reduce size. You can still end up calling deallocate though, if it required capacity to grow, triggering reallocation. In your code, that call to deallocate is inside reserve, called by resize.
Last edited on
llocate obtains raw memory, construct creates objects in it (executes constructors), destroy kills those objects (executes destructors), deallocate returns the raw memory to wherever it came from.

In a vector, specifically, memory between data+size and data+capacity is allocated, but not filled with objects: construct was either never called on it or was followed by destroy.



https://stackoverflow.com/questions/1885849/difference-between-new-operator-and-operator-new

I think I get it now the operator new allocates a certain amount of bytes (allocate ) but doesn't create an object in this memory

where as the new expression for example int *p = new int[5]; allocates and creates(constructs) an object(s) in that memory?

thanks
and apart from writing containers,when would you need to allocate memory manually like in the example instead of just calling new (allocate and create an object in that memory)?
Topic archived. No new replies allowed.