要求提升游泳池体验。作为具有预分配的分配器有用吗?

时间:2014-02-16 14:02:25

标签: c++ memory-management boost allocation objectpool

最近我一直在寻找一个池/分配器机制。 Boost Pool似乎提供了解决方案,但仍有一些东西,它无法从文档中推断出来。

需要分配什么

  1. 几个小班(约30个字符)
  2. std :: map(我想确保它不会自动执行动态分配器)
  3. 在pugi :: xml
  4. 中分配
  5. 的std ::字符串
  6. 如何控制地址空间以进行分配(或仅限数量)

    object_pool似乎提供了分配需求的好方法1) 但是,它希望为分配器设置固定大小。默认情况下它会抓住内存。 如果可能的话,我想给它一个可以在其中播放的地址空间。

    char * mem_for_class[1024*1024];
    boost::object_pool<my_class,mem_for_class> q;
    

    或:

    const int max_no_objs=1024;
    boost::object_pool<my_class,max_no_objs> q;
    

    尽管UserAllocator在Boost :: Pool中可用;它似乎打败了这一点。我担心所需的控制会使效率太低......而且从头开始会更好。

    可以为pool_allocator设置固定区域吗?

    问题与第一个问题有点类似。 在将boost :: pool_allocator提供给std-type-class(例如map)时,boost pool是否可以限制分配内存的数量/位置

    我的场景

    嵌入式linux编程。系统必须继续运行。所以我们不能冒任何内存分段的风险。目前我主要是静态分配(堆栈),还有一些原始的“新”。 我想要一个分配方案,确保每次程序循环时我使用相同的内存区域。 速度/空间很重要,但安全仍然是首要任务。

    我希望StackOverflow可以提问。我试图联系Boost :: Pool“Stephen”的作者,但没有运气。我还没有找到任何特定于Boost的论坛。

1 个答案:

答案 0 :(得分:4)

您始终可以创建一个与STL一起使用的分配器。如果它适用于STL,它应该与boost一起工作,因为你可以将boost分配器传递给STL容器。

考虑到上述情况,可以在指定的内存地址分配并且具有您指定的大小限制的分配器可以写成如下:

#include <iostream>
#include <vector>

template<typename T>
class CAllocator
{
    private:
        std::size_t size;
        T* data = nullptr;

    public:
        typedef T* pointer;
        typedef const T* const_pointer;

        typedef T& reference;
        typedef const T& const_reference;

        typedef std::size_t size_type;
        typedef std::ptrdiff_t difference_type;

        typedef T value_type;


        CAllocator() {}
        CAllocator(pointer data_ptr, size_type max_size) noexcept : size(max_size), data(data_ptr) {};

        template<typename U>
        CAllocator(const CAllocator<U>& other) noexcept {};

        CAllocator(const CAllocator &other) : size(other.size), data(other.data) {}

        template<typename U>
        struct rebind {typedef CAllocator<U> other;};

        pointer allocate(size_type n, const void* hint = 0) {return &data[0];}
        void deallocate(void* ptr, size_type n) {}
        size_type max_size() const {return size;}
};

template <typename T, typename U>
inline bool operator == (const CAllocator<T>&, const CAllocator<U>&) {return true;}

template <typename T, typename U>
inline bool operator != (const CAllocator<T>& a, const CAllocator<U>& b) {return !(a == b);}





int main()
{
    const int size = 1024 / 4;
    int ptr[size];
    std::vector<int, CAllocator<int>> vec(CAllocator<int>(&ptr[0], size));

    int ptr2[size];
    std::vector<int, CAllocator<int>> vec2(CAllocator<int>(&ptr2[0], size));

    vec.push_back(10);
    vec.push_back(20);
    vec2.push_back(30);
    vec2.push_back(40);


    for (std::size_t i = 0; i < vec2.size(); ++i)
    {
        int* val = &ptr2[i];
        std::cout<<*val<<"\n";
    }

    std::cout<<"\n\n";

    vec2 = vec;

    for (std::size_t i = 0; i < vec2.size(); ++i)
    {
        int* val = &ptr2[i];
        std::cout<<*val<<"\n";
    }

    std::cout<<"\n\n";
    vec2.clear();

    vec2.push_back(100);
    vec2.push_back(200);

    for (std::size_t i = 0; i < vec2.size(); ++i)
    {
        int* val = &ptr2[i];
        std::cout<<*val<<"\n";
    }
}

此分配器确保在指定地址分配所有内存。除了你指定的数量之外,无论是在堆栈还是堆上,都可以自由分配。

您可以创建自己的池,也可以使用std::unique_ptr作为单个容器的池。

编辑:对于字符串,您需要sizeof(_Rep_base)的偏移量。请参阅:Why std::string allocating twice?

http://ideone.com/QWtxWg

定义为:

struct _Rep_base
{
    std::size_t     _M_length;
    std::size_t     _M_capacity;
    _Atomic_word        _M_refcount;
};

所以示例变为:

struct Repbase
{
    std::size_t     length;
    std::size_t     capacity;
    std::int16_t    refcount;
};

int main()
{
    typedef std::basic_string<char, std::char_traits<char>, CAllocator<char>> CAString;

    const int size = 1024;
    char ptr[size] = {0};

    CAString str(CAllocator<char>(&ptr[0], size));
    str = "Hello";

    std::cout<<&ptr[sizeof(Repbase)];
}