您如何确定由“ std :: map”创建的,与“ boost :: pool_allocator”一起使用的节点的大小(以跨平台方式)?

Dan*_*aum 5 c++ boost memory-management pool c++11

更新

根据评论,答案和其他研究,我得出的结论是setmap在节点开销方面,a 和a 之间通常没有区别。我的以下问题确实是:

如何确定节点开销以方便 boost::pool_allocator用作自定义分配器?

而且,进一步的更新:节点的开销大概是永远不会超过4个三分球的大小,所以只是清除了Boost池为sizeof(T)sizeof(T)+sizeof(int)sizeof(T) + 2*sizeof(int)sizeof(T) + 3*sizeof(int)sizeof(T) + 4*sizeof(int)(或int64_t64位系统)应罚款。那就是我实际上在做的,并且有效。


我想通过避免调用这些对象的析构函数,而不是在每条包含多个实例的单个条带中释放内存,来使用增强内存池来管理数千万个大小相同的微小对象。

我发布关于此问题的另一个问题,这个问题的答案使我明白,我真正需要回答的问题就是我在这里问的那个问题。

考虑以下代码:

class Obj { // ... has an operator<() ... };

typedef std::set<Obj, std::less<Obj>, boost::fast_pool_allocator<Obj>> fast_set_obj;

// Deliberately do not use a managed pointer -
// I will *NOT* delete this object, but instead
// I will manage the memory using the memory pool!!!
fast_set_obj * mset = new fast_set_obj;

// ... add some Obj's to 'mset'
mset->insert(Obj());
mset->insert(Obj());

// Do something desireable with the set ...
...

// All done.
// It's time to release the memory, but do NOT call any Obj destructors.
// The following line of code works exactly as intended.

boost::singleton_pool<boost::fast_pool_allocator_tag, sizeof(Obj const)>::purge_memory();
Run Code Online (Sandbox Code Playgroud)

如果您进入purge_memory()最后一行代码的功能,您将看到,可以按照需要fast_pool_allocator很好地从系统中释放内存。(没有Obj调用析构函数,因为如上面链接的问题所述,自定义分配器的工作只是分配和释放内存,而不是调用构造函数或析构函数。)

它完全可以按需工作。大!

但是,这就是问题所在。如果您将替换setmap,然后尝试使用boost::pool_allocator,则对的调用不会发生任何反应purge_memory()

typedef std::map<int, int, std::less<int>,
                 boost::fast_pool_allocator<std::pair<int const, int>>>
        fast_map_obj;

// Ditto above: Deliberately do not use managed pointer
mast_map_obj * mmap = new fast_map_obj;

mmap[5] = Obj();
mmap[6] = Obj();

...

// Uh-oh.  The following line of code DOES NOTHING, because I was using a map, not a set!

boost::singleton_pool<boost::fast_pool_allocator_tag,
                     sizeof(std::pair<int const, int>)>::purge_memory();
Run Code Online (Sandbox Code Playgroud)

如前所述,最后一行代码不执行任何操作。原因是boost::fast_pool_allocators是一个单例,仅对在编译时固定的给定大小的对象进行响应并管理其内存。这就是为什么在sizeof调用的表达式中使用该参数的原因purge_memory()-它告诉Boost Pool代码清除各种不同的单例内存池中的一个(假定由于先前已实例化而存在请求的内存池)。

不幸的是,因为选择要清除的内存池取决于大小,所以了解被管理(即在通过调用自定义分配器分配的内存中创建和销毁)内部对象的大小至关重要。遗憾的是,对于std::map,由管理的内部对象的大小map既不是也不sizeof(Obj)sizeof(std::pair<int const, Obj>)

我的问题是:如何严格按照C ++ 11标准以跨平台的方式工作,确定内部std::map使用的对象的大小boost::fast_pool_allocator

这有可能吗?

Nev*_*vin 2

问题是您不知道set用于节点的内部类型。

虽然我还没有弄清楚如何在编译时确定这一点,但您可以编写一个跟踪分配器,sizeof在调用时打印出节点类型allocate,如下所示:

template<typename T>
struct SimpleAllocator : private std::allocator<T>
{
    using value_type = T;
    using pointer = typename std::allocator<T>::pointer;
    using size_type = typename std::allocator<T>::size_type;

    pointer allocate(size_type n)
    {   
        std::cout << "Allocator sizeof(T)==" << sizeof(T) << '\n';
        return std::allocator<T>::allocate(n);
    }   

    void deallocate(pointer p, size_type n)
    { return std::allocator<T>::deallocate(p, n); }
};
Run Code Online (Sandbox Code Playgroud)

还有一个小测试程序(我正在使用整数集进行测试):

std::set<int, std::less<int>, SimpleAllocator<int>> s;
s.insert(2);
Run Code Online (Sandbox Code Playgroud)

在我的系统上,我得到以下输出:

分配器 sizeof(T)==32