1

Suppose I have a std::vector<std::string>.

Even if I specify a custom allocator for the vector, my std::string-s will still use the standard string allocator.

Can I use custom allocator to be shared for both the container and the containees?

2
  • I think this question is too broad. There are 3 separate questions: how to use allocator for a simple class, how to use an allocator for a hierarchically allocated class, and how to write an allocator aware container. All 3 of these are big questions in their own right. If you know the answer to the first I'd suggest separate questions for the second and third; if you don't know the answer to the first you should start by reading about it (plenty of answers already). Commented Oct 16, 2017 at 13:40
  • 1
    I guess question is "how to use an allocator for a hierarchically allocated class" will think how to edit. Commented Oct 16, 2017 at 13:42

2 Answers 2

2

If you have an allocator that you want to use with a hierarchical container, the standard library provides a solution: scoped_allocator_adaptor. When you use the adapter, it forces that allocator to be passed downwards to any allocator aware container. This requires that the container correctly specializes the allocator aware trait, and that all of its constructors have an overload that takes an allocator last. Here's the example of usage from http://en.cppreference.com/w/cpp/memory/scoped_allocator_adaptor:

namespace bi = boost::interprocess;
template<class T> using alloc = bi::adaptive_pool<T,
                                    bi::managed_shared_memory::segment_manager>;
using ipc_row = std::vector<int, alloc<int>>;
using ipc_matrix = std::vector<ipc_row, std::scoped_allocator_adaptor<alloc<ipc_row>>>;

One thing to note is that allocators are of course part of the type of the container. So this doesn't get you out of needing to specify the correct allocator type for the inner container. What this does is ensure the allocator instance gets passed down. This is important for allocators which are not stateless. The example continues:

bi::managed_shared_memory s(bi::create_only, "Demo", 65536);

// create vector of vectors in shared memory
ipc_matrix v(s.get_segment_manager());

As you might get this allocator is not stateless.

If you have a stateless allocator you don't need to deal with any of this, you would just define the type of the outer and inner containers to use the same allocator and that would be that.

I won't get into it here, but another approach is to use the new pmr approach to allocators. It hasn't been merged into the standard. It does make things quite a bit simpler because everything is type-erased and I believe it passes down to nested containers automatically. You can find a library implementation of it somewhere if you google.

Sign up to request clarification or add additional context in comments.

Comments

2

Suppose I have std::vector of std::string. How can I use custom allocator for it? I can do allocator for the vector, but then I need to do for strings as well?

When you use a custom allocator for a container, you command the container to allocate memory using your allocator.

A container cannot be responsible for any allocations performed by the Object it contains, so yes, you will have to use std::basic_string with a custom allocator as well.

Suppose I have own class, similar to linked list of std::string. How can I use custom allocator for it? Shall I do my own implementation or say replace malloc with xmalloc etc.

Again, a container should NOT be responsible/aware of allocations performed by its containees! Instead, use std::basic_string with a custom allocator.

scoped_allocator_adaptor

Regarding the updated question, as Nir Friedman's answer suggests, scoped_allocator_adaptor is a standard solution for using the same allocator for a container and its containees.

This doesn't mean that the container is responsible for the allocations of the containee, but rather that they both share the same allocator.

4 Comments

Sorry, but this post is mostly incorrect. Multi level container allocation is a known problem and has solutions within the standard library; the separation of concerns you are suggesting is not a good one. See: en.cppreference.com/w/cpp/memory/scoped_allocator_adaptor.
@NirFriedman, could you please add some links to references on the matter?
I provided a link to scoped_allocator_adaptor. I think that's sufficient?
@NirFriedman, thanks for your input. I still think that the container should not be responsible for allocations of containees. The correct terminology would be: A container that shares its allocator with its containees (whether explicitly or implicitly). Nonetheless, your solution seems great and was the right one for the OP :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.