私は、C++ で設定されたサードパーティの C API を使用しています。これには、この議論に関係する 2 つの方法があります。
- これは malloc() と同等です: the_api_malloc(size) (および一致する the_api_free())
- the_api_malloc() で作成されたメモリが返され、その所有権と the_api_free() の所有権が内部的に取得される関数: the_api_give_back(ptr)
たとえば、std::vector で使用するために、the_api_malloc() および the_api_free() をラップするカスタム アロケータを作成しました。これはうまくいきます。
私がしたいのは、カスタム アロケータを利用する 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;
}
}
より良い方法はありますか?
UPDATE 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() を機能させることができません。