0

A挿入中に各オブジェクトのコピーを作成せずに、コンテナ オブジェクト内にタイプの複数のオブジェクトを挿入する方法を探していAます。1 つの方法は、コンテナーへの参照によってオブジェクトを渡すことAですが、残念ながら、私が読んだ限りでは、STL コンテナーは、挿入のために値によるオブジェクトの受け渡しのみを受け入れます (多くの正当な理由により)。通常、これは問題にはなりませんが、私の場合、コピー コンストラクターが呼び出されて元のオブジェクトが破棄されることは望ましくありません。これAは、C ライブラリのラッパーであり、内部に構造体への C スタイルのポインターがあるためです。 、元のオブジェクトと一緒に削除されます...

特定のインデックスを指定して、そのオブジェクトの 1 つを返し、実行時に決定される特定の数のアイテムを格納できるコンテナーのみが必要なので、独自のコンテナー クラスを作成できるのではないかと考えましたが、方法がわかりません。これを適切に行うこと。

別のアプローチはA、コンテナー内へのポインターを格納することですが、この件に関する知識があまりないため、STL コンテナー内のオブジェクトへのポインターを挿入する適切な方法は何でしょうか? たとえば、次のようになります。

std::vector<A *> myVector;
for (unsigned int i = 0; i < n; ++i)
{
    A *myObj = new myObj();
    myVector.pushBack(myObj);
}

うまくいくかもしれませんが、適切に処理する方法ときれいに処分する方法がわかりません。myVector をメンバーとして含むクラスのデストラクタだけに頼って破棄する必要がありますか? 含まれているオブジェクトの 1 つを削除しているときに、このデストラクタが例外をスローするとどうなりますか?

shared_ptrまた、ややのようなものを使うことを提案する人もいauto_ptrますunique_ptrが、私は非常に多くのオプションに混乱しています。私のシナリオに最適なのはどれですか?

4

2 に答える 2

5

boostまたはを使用できますstd reference_wrapper

#include <boost/ref.hpp>
#include <vector>

struct A {};


int main()
{
  A a, b, c, d;
  std::vector< boost::reference_wrapper<A> > v;
  v.push_back(boost::ref(a)); v.push_back(boost::ref(b)); 
  v.push_back(boost::ref(c)); v.push_back(boost::ref(d));
  return 0;
}

reference_wrapperを使用してダングリング参照を取得しない場合は、オブジェクトの有効期間に注意する必要があります 。

int main()
{
  std::vector< boost::reference_wrapper<A> > v;
  {
    A a, b, c, d;
    v.push_back(boost::ref(a)); v.push_back(boost::ref(b)); 
    v.push_back(boost::ref(c)); v.push_back(boost::ref(d));
    // a, b, c, d get destroyed by the end of the scope
  }
  // now you have a vector full of dangling references, which is a very bad situation
  return 0;
}

このような状況を処理する必要がある場合は、スマート ポインターが必要です。

スマート ポインターもオプションですが、どれを使用するかを知ることが重要です。データが実際に共有されているshared_ptr場合は、コンテナーがデータを所有している場合に使用しますunique_ptr

とにかく、ラッパー部分が何を変更するかわかりませんA。内部にポインターが含まれていて、3 の規則に従っている場合、問題は発生しません。デストラクタがクリーンアップを処理します。これは、C++ でリソースを処理する一般的な方法です。オブジェクトが初期化されたときにリソースを取得し、オブジェクトの有効期間が終了したときにそれらを削除します。

純粋に構築と削除のオーバーヘッドを避けたい場合は、vector::emplace_back.

于 2012-06-19T15:35:05.803 に答える
4

C++11 では、関数を使用してコンテナー要素をその場で構築できるemplaceため、割り当てられたオブジェクトへのポインターのコンテナーを管理するコストと面倒を回避できます。

std::vector<A> myVector;
for (unsigned int i = 0; i < n; ++i)
{
    myVector.emplace_back();
}

オブジェクトのコンストラクターが引数を取る場合は、それらをemplace関数に渡します。関数はそれらを転送します。

ただし、オブジェクトは、ベクトルのストレージが再割り当てされるときに移動する必要があるため、コピー可能または移動可能である場合にのみベクトルに格納できます。オブジェクトを移動可能にしたり、管理対象リソースの所有権を譲渡したり、またはオブジェクトが成長しても移動しないようなコンテナーを使用したりすることを検討してくださいdequelist

更新:これはコンパイラでは機能しないため、おそらく最良のオプションはstd::unique_ptr、通常のポインターと比較してオーバーヘッドがなく、ベクターから消去されたときにオブジェクトを自動的に削除し、所有権をベクターから移動できるようにすることです。あなたがしたい。

それが利用できない場合は、std::shared_ptr(またはstd::tr1::shared_ptr、それが利用できない場合は またはboost::shared_ptr)も自動削除を提供し、(おそらく小さな)効率のコストを削減します。

何をするにしても、標準的な容器に保管しようとしないでください. std::auto_ptrその破壊的なコピー動作により、予期しないときに誤ってオブジェクトを削除することが容易になります。

これらのいずれも利用できない場合は、例のようにポインターを使用し、オブジェクトを使い終わったら忘れずにオブジェクトを削除してください。

于 2012-06-19T15:52:01.780 に答える