How to use std::allocators in my template class

Hello All,
I have developed a template class where I use operator::new() and operator::delete() to allocate and deallocate the memory.
I want to start using the std::allocators in it as the default allocator. Also, I want to have my template class accept an allocator in case I want to use the boost::pool_allocators().
I searched the internet and there is no tutorials on how to do that.

Please, can you tell me:
1- How to specify the default allocator for my template?
2- how can I replace all the new with std::allocate, given that I also have allocate memory for objetcs and I want to make sure that the constructors are called.

Thanks
zarzor2010 wrote:
1- How to specify the default allocator for my template?

You can write your class template to accept an Allocator parameter.
This is how C++ standard containers are typically written.

Sources of inspiration:
http://en.cppreference.com/w/cpp/concept/AllocatorAwareContainer
http://en.cppreference.com/w/cpp/memory/allocator
http://en.cppreference.com/w/cpp/container/forward_list
http://llvm.org/svn/llvm-project/libcxx/trunk/include/forward_list

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <memory>

// ...

template <typename T, typename Allocator = std::allocator<T> >
class example
{
public:

    explicit example(const Allocator &a = Allocator())
    {
        // ...
    }
};


zarzor2010 wrote:
2- how can I replace all the new with std::allocate, given that I also have allocate memory for objetcs and I want to make sure that the constructors are called.


operator new does two things automatically:
1) allocates memory
2) calls constructor to initialize that memory

operator delete does two things as well:
3) calls destructor on allocated memory
4) deallocates memory

By using an allocator, you must do these four things yourself:
1) http://en.cppreference.com/w/cpp/memory/allocator/allocate
2) http://en.cppreference.com/w/cpp/memory/allocator/construct
3) http://en.cppreference.com/w/cpp/memory/allocator/destroy
4) http://en.cppreference.com/w/cpp/memory/allocator/deallocate
Last edited on
Thank you so much,
Just a couple of questions thought,

1- why did you use explicit for the constructor? is it a requirement when using Allocator?

2- is it safe to allocate the memory and then call the constructors (ie. it makes sure that the memory is correctly aligned) ?
And what if I the "T" was "int" for example, does calling the allocator::construct() on an int causes problems?

Thanks
zarzor2010 wrote:
1- why did you use explicit for the constructor? is it a requirement when using Allocator?

A constructor that can be called with a single parameter can serve a secondary purpose, of implicitly "converting" the parameter.
The keyword explicit ensures that constructors will not be used implicitly.

Note that explicit only makes sense for constructors that can be called with a single parameter.

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
class A
{
public:

    A(int )
    {
    }
};

class B
{
public:

    explicit B(int )
    {
    }
};

void func_a(A )
{
}

void func_b(B )
{
}

int main()
{
    A a1 = 100;     // works
    A a2 = A(200);  // works
    A a3(300);      // works
    B b1 = 100;     // doesn't work
    B b2 = B(200);  // works
    B b3(300);      // works

    func_a(400);    // works
    func_a(A(500)); // works
    func_b(400);    // doesn't work
    func_b(B(500)); // works
}


As you can see above, func_a() can be called with a regular int even though it expects an A object.
This is because the int is implicitly converted to an A.

You can read more here:
http://www.cplusplus.com/doc/tutorial/typecasting/#implicit_conversion
http://www.cplusplus.com/doc/tutorial/typecasting/#explicit
http://en.cppreference.com/w/cpp/language/explicit

zarzor2010 wrote:
2- is it safe to allocate the memory and then call the constructors (ie. it makes sure that the memory is correctly aligned) ?

It doesn't have to do with memory alignment.
Bear in mind that constructors do not allocate memory for the object they "construct": they only initialize the object's member data with values. So the object must have memory allocated for it before the constructor is called.

So you need to use allocate() and then construct(), otherwise you will probably be writing to memory you don't own, and your program may crash with a Segmentation Fault.

zarzor2010 wrote:
And what if I the "T" was "int" for example, does calling the allocator::construct() on an int causes problems?

No. It is safe to assume that std::allocator is coded to work correctly on fundamental types such as int.

For example have you ever used std::vector<int> or std::list<int>?
By default, they use std::allocator<int>.

Internally, std::allocator::construct() uses placement new:
http://en.cppreference.com/w/cpp/memory/allocator/construct
http://www.cplusplus.com/reference/memory/allocator/construct/
http://isocpp.org/wiki/faq/dtors#placement-new
http://www.icce.rug.nl/documents/cplusplus/cplusplus09.html#PLACEMENT
Last edited on
Topic archived. No new replies allowed.