2

私は、C++ で設定されたサードパーティの C API を使用しています。これには、この議論に関係する 2 つの方法があります。

  1. これは malloc() と同等です: the_api_malloc(size) (および一致する the_api_free())
  2. 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() を機能させることができません。

4

3 に答える 3

1

vector::swap割り当てられたブロックの所有権を別のブロックに譲渡しvectorます。ただし、ベクトルがそのデストラクタを呼び出すのを停止する方法vector::allocator_type::deallocateはなく、内部ポインタを直接変更する移植可能な方法もありません。

于 2010-08-26T23:19:04.127 に答える
1

ベクターがアロケーターの無料関数を呼び出すのを止めようとする代わりに、アロケーターのreleaseメンバーとしてあなたを含め、フラグを設定します。フラグが設定さthe_api_freeれると、単純に戻ります (つまり、nop として機能します)。

于 2010-08-26T22:49:50.853 に答える