Распределители C++, в частности передача аргументов конструктора объектам, выделенным с помощью boost::interprocess::cached_adaptive_pool

Это неловкий вопрос, но даже хорошо написанной документации, поставляемой с boost.interprocess, мне недостаточно, чтобы понять, как это сделать.

У меня есть cached_adaptive_pool. экземпляр распределителя, и я хочу использовать его для создания объекта, передавая параметры конструктора:

struct Test {
  Test(float argument, bool flag);
  Test();
};

// Normal construction
Test obj(10, true);
// Normal dynamic allocation
Test* obj2 = new Test(20, false);

typedef managed_unique_ptr<
    Test, boost::interprocess::managed_shared_memory>::type unique_ptr;

// Dynamic allocation where allocator_instance == cached_adaptive_pool,
// using the default constructor
unique_ptr obj3 = allocator_instance.allocate_one()
// As above, but with the non-default constructor
unique_ptr obj4 = allocator_instance ... ???

Это вполне может быть ошибкой с моей стороны в том, как использовать объекты распределителя в целом. Но в любом случае я не вижу, как использовать этот конкретный распределитель с интерфейсом, указанным в cached_adaptive_pool для передачи аргументов конструктора моему объекту.

cached_adaptive_pool есть метод: void construct(const pointer & ptr, const_reference v) но я не понимаю, что это значит, и не могу найти примеры его использования.

Весь день моя голова плавала в шаблонах, так что рука помощи, даже если ответ очевиден, будет принята с благодарностью.


person porgarmingduod    schedule 07.04.2010    source источник


Ответы (2)


cached_adaptive_pool имеет метод: конструкция void (const pointer & ptr, const_reference v), но я не понимаю, что это значит, и не могу найти примеры его использования.

Он должен следовать интерфейсу std::allocator, и в этом случае allocate() дает вам подходящий фрагмент неинициализированной памяти, а construct() вызывает размещение нового по данному указателю.

Что-то типа:

allocator_instance.construct(allocator_instance.allocate_one(), Test(30, true));

Хотя сам этими бассейнами не пользовался. В C++0x аллокаторы должны иметь возможность вызывать любой конструктор, а не только конструктор копирования, так что, возможно, аллокаторы boost уже в какой-то степени поддерживают это.

a.construct(p, 30, true); //a C++0x allocator would allow this and call new (p) Test(30, true)
person UncleBens    schedule 07.04.2010
comment
Спасибо. Первая форма — это ответ, которого я ожидал, но был слишком сбит с толку и устал, чтобы осознать себя. Вторая форма a.construct(p, 30, true), похоже, не поддерживается этим конкретным распределителем повышения. Досадно, что поскольку cached_adaptive_pool.construct() возвращает void, мне приходится писать allocator_t::pointer obj = allocator.allocate_one(); allocator.construct(obj, Test(30, true))? Я не уверен, что хуже, использовать два оператора для одной простой операции или использовать несколько странно выглядящее новое размещение напрямую. - person porgarmingduod; 08.04.2010
comment
Вы можете сделать это отдельной функцией. - person UncleBens; 08.04.2010

Думаю, я всегда могу использовать синтаксис placement new. Идея состоит в том, чтобы разыменовать интеллектуальный указатель (в данном случае offset_ptr), возвращенный распределителем, а затем передать необработанный адрес в new().

unique_ptr obj = new(&(*allocator_instance.allocate_one())) Test(1,true)

Это идиоматический способ сделать это? В boost есть так много других мест, где предоставляется явная поддержка, чтобы избежать использования нового размещения, что заставляет меня думать, что нет. В любом случае, я приму этот ответ, если в ближайшем будущем не будет предоставлено ничего лучшего.

person porgarmingduod    schedule 07.04.2010
comment
Для чего нужна последовательность &*ptr? - person UncleBens; 08.04.2010
comment
Когда я тестировал его, new принимал только необработанный указатель, а не offset_ptr, который возвращает этот распределитель. - person porgarmingduod; 09.04.2010