6

私は古いオープンソース ライブラリを使用しており、次の (簡略化された) 関心のある API を使用しています。

// some class that holds a raw pointer to memory on the heap
// DOES NOT delete it in its destructor
// DOES NOT do a "deep" copy when copied/assigned (i.e., after copying both objects
// will point to the same address)
class Point;

// function used to construct a point and allocate its data on the heap
Point AllocPoint();
// function used to release the memory of the point's data
void DeallocPoint(Point& p);

// Receives a pointer/c-array of Points, along with the number of points
// Doesn't own the memory
void Foo(Point* points, int npts);

C++ 11 でこの API を使用する最良の (最も安全/最も読みやすく/最もエレガントな) 方法は何ですか? 単純に使用することはできませんvector<unique_ptr<Point, PointDeleter>>(PointDeleterは実装できる単純なカスタム デリータです)。関数を使用できなくなるためですFoo(これは を期待し、 を期待Point*しませんunique_ptr<Point>*)。

ありがとう

4

5 に答える 5

4

本当に見栄えを良くしたい場合は、おそらく、ライブラリの API を完全に隠す一連の非常に包括的なラッパーを作成する必要があります。つまり、ライブラリ全体を、外部で最新の C++ の方法で動作するものでラップします。そしてすべての混乱を内部に隠します。

楽しい作業ではありませんが、そのライブラリの動作を正しくすることができれば、長期的にはあなたの人生がずっと楽になるはずです。ただし、この外部ライブラリを非常に広範囲に使用しない場合は、価値がないかもしれません。

于 2013-06-17T10:42:56.930 に答える
4

を呼び出して使用できます。しかし、ここでメモリを管理するのは難しいかもしれません。要素がコピーされた場合でも、アロケータ内のカスタム デリータが要素ごとに呼び出されます。std::vector<Point>Foo( &v[0], v.size() )Point

ベクトルが実際にポイントを所有する必要がある場合は、より複雑なクラスでラップすることができます。これはAllocPoint、挿入ごと (および結果の挿入)、およびDeallocPoint削除ごと (および破壊時にベクトルに残っているすべてのもの) を呼び出します。ただし、このクラスは(非 const 、非 const イテレータなど) への書き込みアクセスを許可する べきではありません。おそらく、操作するための他の機能があり ます。ラッパー インターフェースを介してこれらを利用できるようにする必要があります。Pointoperator[]PointDeallocPointPoint

于 2013-06-17T10:46:22.240 に答える
4

この非 RAII の C ライクな API をRAIIビルディング ブロックでラップし、C++11 コードで使用します。

例: RaiiPoint(非 RAII)Pointクラスをラップするクラスを定義し、そのコンストラクター呼び出しAllocPoint()で、デストラクタで定義できますDeallocPoint()。次に、適切なコピー コンストラクターと copy を定義するoperator=か、(move コンストラクターと move を使用しoperator=て) 移動セマンティクスを実装するか、要件に基づいてラッパー クラスをコピー可能かつ移動可能にすることができます。

std::vector<RaiiPoint>次に、RAII ベースのラッパー クラスでa を使用するだけです。

(これは、最新の C++ コードで C ライブラリを使用する場合に使用できる一般的なアプローチです。「生の」C ライブラリ ハンドルとオブジェクトを安全な RAII 境界でラップし、これらの堅牢で安全なラッパー クラスを最新の C++ で使用できます。コード。)

于 2013-06-17T10:46:08.170 に答える
1

「あなた」は、メモリを解放するための単純なラッパーを書くことができます:

struct PointVectorWrapper {
  vector<Point> points;
  ~PointVectorWrapper() {
    for (Point& p : points) {
      DeallocPoint(p);
    }
  }
  PointVectorWrapper& operator=(const PointVectorWrapper&) = delete;
  PointVectorWrapper(const PointVectorWrapper&) = delete;
};
// Now the usage is simple and safe:
PointVectorWrapper points;
// ... populate points ...
Foo(points.data(), points.size())

しかし、これは少し「アドホック」に思えます。より標準的/再利用可能なソリューションは何ですか?

于 2013-06-17T10:30:35.340 に答える
1

コンストラクト メソッドで AllocPoint を呼び出し、destruct メソッドで DeallocPoint() を呼び出す、カスタム アロケータで標準ベクトルを使用できます。

template<typename T>
class CustomAllocator : public std::allocator<T>
{
  //Rebind and constructors
};

template<>
class CustomAllocator<Point> : public std::allocator<Point>
{
   //Rebind and constructors

   //For c++11
   void construct( pointer p )
   {
      new (p) Point();
      *p = AllocPoint();
   }

   void construct( pointer p, const_reference val )
   {
      construct(p);
      //copy member from val to point if neccessary 
   };   


   void destroy( pointer p )
   {
      DeallocPoint(*p);
      p->~Point();
   }
};

typedef std::vector<Point, CustomAllocator<Point> > PointVector;
于 2013-06-17T20:25:35.807 に答える