Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use allocators in modern C++

From what I read in http://en.cppreference.com/w/cpp/memory/allocator , most features of the allocators are now going to be deprecated. The question is, how is one supposed to use allocators in new code? What is the "right" way now?

From what I deduce in the documentation, construct is part of the allocator traits, rather than the allocator itself.

I am building a custom container, here it is a very simple version of the constructor, is this a good usage of the new design?

container::container(std::size_t size, T const& value, Allocator const& allocator) : allocator_(allocator){
    data_ = std::allocator_traits<Alloc>::allocate(allocator_, size);
    for(auto ptr = data_; ptr != data_ + size; ++ptr){
        std::allocator_traits<Allocator>::construct(allocator_, ptr, value)
    }
}

I tried to use an algorithm (like std::for_each) in the loop but I didn't manage to use one without taking addresses (operator&).

Where can I find a complete example of a modern allocator?


After some tweaking, I found a way to use an algorithm instead of the the raw loop (to which an execution policy can be passed). I am not very sure, but it could be this:

    data_ = std::allocator_traits<Allocator>::allocate(allocator_, size);
    std::for_each([policy? deduced from allocator?,] 
        boost::make_counting_iterator(data_),
        boost::make_counting_iterator(data_ + size), 
        [&](auto ptr){std::allocator_traits<Allocator>::construct(allocator_, ptr, value);}
    );
like image 452
alfC Avatar asked Dec 18 '16 23:12

alfC


People also ask

Does std :: allocator use malloc?

Struct std::alloc::System The default memory allocator provided by the operating system. This is based on malloc on Unix platforms and HeapAlloc on Windows, plus related functions.

How do allocators work?

Allocators handle all the requests for allocation and deallocation of memory for a given container. The C++ Standard Library provides general-purpose allocators that are used by default, however, custom allocators may also be supplied by the programmer.

Why is allocator construct deprecated?

std::allocator 's construct and destroy are deprecated because they are useless: no good C++11 and later code should ever call them directly, and they add nothing over the default. Handling memory alignment should be the task of allocate , not construct .

What is a std :: allocator?

std::allocator is used when you want to separate allocation and do construction in two steps. It is also used when separate destruction and deallocation is done in two steps. All the STL containers in C++ have a type parameter Allocator that is by default std::allocator.


1 Answers

Yes, the current approach is through std::allocator_traits. You'll be able to support the "minimal allocator interface" that way.

http://en.cppreference.com/w/cpp/concept/Allocator

Some requirements are optional: the template std::allocator_traits supplies the default implementations for all optional requirements, and all standard library containers and other allocator-aware classes access the allocator through std::allocator_traits, not directly.

If you observe the std::allocator_traits member functions and typedefs, you'll see they're detecting the presence of appropriate function/types and dispatching through them if they can.

The deprecation and potential future removal will change nothing if you're already using std::allocator_traits since it only applies to std::allocator and their member functions/typedefs.

Now, if you ask me, there's nothing wrong with for-loops, and using std::for_each gains you nothing. There are several uninitialized_* functions, but they use placement new directly. If you really care you can extract this code to a separate construct_range function.

There's also an exception safety issue - in case one of the constructors throws, you need to destroy the earlier elements in order to satisfy the strong exception guarantee and free the memory too (destructor won't get called in case constructor throws)

like image 181
milleniumbug Avatar answered Oct 11 '22 12:10

milleniumbug