Недавно я искал механизм пула / распределения.
Boost Pool, кажется, обеспечивает решение, но есть еще вещи, которые он не смог вывести из документации.
Кажется, что 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; кажется, победить суть. Боюсь, что необходимый контроль сделает его слишком неэффективным … и было бы лучше начать с нуля.
Вопрос немного похож на первый.
Обеспечивает ли пул наддува любой способ ограничения того, сколько / где выделено памяти при передаче boost :: pool_allocator классу std-type (например, map)
Встроенное программирование Linux. Система должна продолжать работать вечно. Поэтому мы не можем рисковать любой сегментацией памяти. В настоящее время я в основном либо статическое распределение (стек), но также несколько необработанных «новых».
Я хотел бы схему распределения, которая гарантирует, что я использую одну и ту же область памяти каждый раз, когда программа зацикливается.
Скорость / пространство важны, но безопасность по-прежнему является главным приоритетом.
Я надеюсь, что StackOverflow — это место, где можно спросить. Я безуспешно пытался связаться с автором Boost :: Pool «Stephen». Я не нашел ни одного форума для Boost.
Вы всегда можете создать распределитель, который работает с 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)
, Увидеть: Почему std :: string выделяется дважды?
а также 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)];
}
Использование std :: map вводит много дополнительного синтаксиса … который может сбивать с толку … пока не повезло
Я не могу легко определить, что я делаю неправильно. Попытка пока:
typedef CAllocator<std::pair<const int, char>> pair_alloc;
void test_allocator_with_map()
{
const int size=2048;
std::pair<int, char> mem[size];
//auto dummy = pair_alloc(mem[0],size); //the problem seems to be my cStor parameters... this also fail
std::map<int,char,std::less<int>,pair_alloc> myMap1(pair_alloc(mem[0],size));
myMap1[4]='l';
std::cout<< myMap1[4] << "\n";
};
//signature of std::map
// <typename _Key,
// typename _Tp,
// typename _Compare = std::less<_Key>,
// typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
// std::pair<const _Key, _Tp>
Я думаю, что первый шаг, скорее, должен написать шаблон, который перенаправляет параметры в шаблон std :: map