Я работаю с набором C API третьей стороны в C++, который имеет два методы беспокойства для этой дискуссии:Пользовательский распределитель для std :: vector <> с выпуском?
- Это эквивалентно таНос(): the_api_malloc (размер) (плюс соответствующий the_api_free())
- функция, в которой память создана с the_api_malloc() возвращается к тому, что имеет право собственности на него и the_api_free() 'ы это внутренне: the_api_give_back (PTR)
Я создал пользовательский распределитель wrapp используя the_api_malloc() и the_api_free() для использования, например, с помощью std :: vector. Это отлично работает.
Что я хотел бы сделать, это иметь класс std :: vector type, который использует мой собственный распределитель, но также имеет метод release(), который при вызове освобождает право собственности на его память и поэтому не будет вызывать мои пользовательские распределители the_api_free().
pointer release() /* pointer is of T* */
Пример использования:
MyClass myClass(1024); // the_api_malloc()'s 1024 bytes
// ... do something with myClass
the_api_give_back(myClass.release());
Я не уверен, что лучший способ осуществить это. То, что я имею сейчас в качестве эксперимента, довольно противное:
class MyClass : public std::vector<char, MyAllocator<char> > {
public:
using typename std::vector<char, MyAllocator<char> >::pointer;
pointer release() {
// note: visual studio impl.
pointer p = this->_Myfirst;
this->_Myfirst = 0;
this->_Mylast = 0;
this->_Myend = 0;
return p;
}
}
Есть ли лучший способ?
ОБНОВЛЕНИЕ 1: Вот что я пробовал на основе предложений ниже. Это также должно помочь проиллюстрировать желаемое поведение &, где он в настоящее время не работает.
template <class T>
class MyAllocator
{
public:
// types omitted for clarity
MyAllocator() : m_released(false) { }
template <class U>
MyAllocator(MyAllocator<U> const& a) : m_released(a.m_released) { }
// other ctors, dtors, etc. omitted for clarity
// note: allocate() utilizes the_api_malloc()
void deallocate(pointer p, size_type num)
{
if(!m_released) {
the_api_free(p);
}
}
void release_ownership() { m_released = true; }
bool m_released;
};
template <typename T>
char* ReleaseOwernship(T& container)
{
container.get_allocator().release_ownership();
return &container[0];
}
// usage:
{ // scope
std::vector<char, MyAllocator<char> > vec;
// ...do something to populate vec...
char* p = ReleaseOwnership(vec);
the_api_give_back(p); // this API takes ownership of p and will delete it itself
} // end scope - note that MyAllocator::deallocate() gets called here -- m_release is still false
UPDATE 2: Пытался создать MyOwningAllocator и MyNonOwningAllocator затем обменивать из владеющих на не владеющий где на «время выхода», но не может получить своп(), чтобы работать, как они отличаются типы.
Аботаторы не имеют состояния, поэтому я не уверен, как у меня может быть флаг в одном? – NuSkooler
@NuSkooler: точнее, стандартная библиотека не * требуется * для поддержки распределителей, имеющих состояние. Тем не менее, это первое, что я попробую. Если память используется, C++ 0x требует, чтобы они поддерживали генераторы с сохранением состояния, поэтому я бы предположил, что есть приличный шанс, что это сработает. Я бы сделал только что-то другое, если вы считаете, что это действительно необходимо. –
Я создал release_ownership() в своем настраиваемом распределителе, который устанавливает значение члена bool. В deallocate() bool проверяется и ничего не делает, если true. Тем не менее, адрес всегда отличается между release_ownership() и deallocate(), поэтому bool всегда false (это значение по умолчанию ctor). – NuSkooler