Я работаю с C API стороннего разработчика, установленным на C ++, для которого обсуждаются два метода:
- Это эквивалентно malloc (): the_api_malloc (размер) (плюс соответствующий the_api_free ())
- Функция, в которой возвращается память, созданная с помощью the_api_malloc (), которая получает ее и внутреннюю принадлежность the_api_free (): the_api_give_back (ptr)
Я создал собственный распределитель, обертывающий the_api_malloc () и the_api_free () для использования, например, с std :: vector. Это прекрасно работает.
То, что я хотел бы сделать, это иметь класс типа std :: vector, который использует мой пользовательский распределитель, но также имеет метод 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
ОБНОВЛЕНИЕ 2: Попытка создания MyOwningAllocator и MyNonOwningAllocator с последующим переключением из владения в не принадлежащее, где во время «выпуска», но не может заставить работать swap (), поскольку они отличаются типы.