Memory allocation via std::allocator.

Really need some confirmation on whether I got this right or not, specifically the part where the allocator is being constructed in reallocate() and push_back().

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
class StrVec
{
public:
    StrVec():
        elements(nullptr), first_free(nullptr), cap(nullptr) { }
    void push_back(const std::string&);
    size_t size() const { return first_free - elements; }
    size_t capacity() const { return cap - elements; }
 

private:
    static std::allocator<std::string> alloc;
    void chk_n_alloc()
        { if (size() == capacity()) reallocate(); }

    void free();
    void reallocate();

    std::string *elements;      //First element
    std::string *first_free;    //One past last actual(value filled) elem.
    std::string *cap;           //Reserved capacity

};

void StrVec::push_back(const string& s)
{
    chk_n_alloc();
    alloc.construct(first_free++, s);
}


void StrVec::reallocate()
{
    auto newcapacity = size() ? 2 * size() : 1;

    auto newdata = alloc.allocate(newcapacity);

    auto dest = newdata; 
    auto elem = elements; 

    for (size_t i = 0; i != size(); ++i)
        alloc.construct(dest++, std::move(*elem++));
   
    elements = newdata;
    first_free = dest;
    cap = elements + newcapacity;
}


In reallocate(), is the construct constructing empty string elements which is filled in with the call to construct from push_back()?
Last edited on
the part where the allocator is being constructed in reallocate() and push_back().

The allocator is not constructed there, the allocator is a static data member of StrVec and is constructed, presumably, in some .cpp file.

In reallocate(), is the construct constructing empty string elements

It is moving the existing string elements from the old storage into the new storage. If you didn't push_back any empty strings, it never constructs an empty string.

Note that it leaks memory at line 44 where the pointer to the old storage is lost, and again when StrVec is destructed.
Thanks for the answer, still need a little nudge though. So let's say on the first call to push_back in main(), since there is no old data...

1
2
for (size_t i = 0; i != size(); ++i)
        alloc.construct(dest++, std::move(*elem++));


...doesn't actually do anything? And alloc has one raw memory to be used in the call to construct in push_back()?

Would it be okay to say that an allocator is like a vector in the sense that its' like a container?

I removed the function and destructor that is suppose to be in this class because I thought it wasn't really relevant.
On the first call to push_back() in main, size() is zero, so the loop is never entered.
size() is zero, so the loop is never entered.


That explains so much! Thanks Cubbi =)
Topic archived. No new replies allowed.