简体   繁体   中英

How to use an allocator for a hierarchically allocated class

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?

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM