オブジェクト全体、またはコンテナへのオブジェクトへのポインタを保存する必要がありますか?
質問
新しいシステムをゼロから設計する。 STLを使用して、特定の長寿命オブジェクトのリストとマップを保存します。
質問:オブジェクトにコピーコンストラクターがあり、STLコンテナー内にオブジェクトのコピーを保存することを確認する必要がありますか、それとも一般的に<!> amp;を管理する方が良いでしょうか。自分をスコープし、それらのオブジェクトへのポインタをSTLコンテナに保存するだけですか?
これは詳細がやや短いことがわかりますが、<!> quot;理論上の<!> quot;を探しています。これらの解決策の両方が可能であることを知っているので、それが存在する場合、より良い答え。
ポインターで遊ぶことの2つの非常に明白な欠点: 1)これらのオブジェクトの割り当て/割り当て解除は、STLを超える範囲で自分で管理する必要があります。 2)スタックに一時オブジェクトを作成して、コンテナに追加できません。
不足しているものは他にありますか?
解決
人々はポインターを使用することの効率性に賛成しているため。
std :: vectorの使用を検討しており、更新が少なく、コレクションを繰り返し処理することが多く、オブジェクトを格納する非ポリモーフィック型の場合<!> quot; copies <!> quot;参照の局所性が向上するため、より効率的になります。
Otoh、更新が一般的な場合、ポインターを保存するとコピー/再配置のコストが節約されます。
他のヒント
これは本当にあなたの状況に依存します。
オブジェクトが小さく、オブジェクトのコピーを行うのが軽量である場合、stlコンテナ内にデータを保存することは簡単であり、ライフタイム管理を心配する必要がないため、私の意見では管理が容易です。
オブジェクトが大きく、デフォルトのコンストラクターを使用しても意味がない場合、またはオブジェクトのコピーが高価な場合は、おそらくポインターを使用して保存する方法があります。
オブジェクトへのポインターを使用する場合は、ブーストポインタコンテナライブラリ。このブーストライブラリは、動的に割り当てられたオブジェクトで使用するためにすべてのSTLコンテナーをラップします。
各ポインタコンテナ(ptr_vectorなど)は、コンテナに追加されたオブジェクトの所有権を取得し、それらのオブジェクトの有効期間を管理します。また、参照によってptr_コンテナー内のすべての要素にアクセスします。これにより、次のようなことができます
class BigExpensive { ... }
// create a pointer vector
ptr_vector<BigExpensive> bigVector;
bigVector.push_back( new BigExpensive( "Lexus", 57700 ) );
bigVector.push_back( new BigExpensive( "House", 15000000 );
// get a reference to the first element
MyClass& expensiveItem = bigList[0];
expensiveItem.sell();
これらのクラスはSTLコンテナをラップし、すべてのSTLアルゴリズムで動作します。これは非常に便利です。
コンテナ内のポインタの所有権を呼び出し側に転送する機能もあります(ほとんどのコンテナのリリース機能を使用)。
多面体オブジェクトを保存する場合は、常に基本クラスポインターのコレクションを使用する必要があります。
つまり、コレクションに異なる派生型を保存する予定がある場合は、ポインターを保存するか、スライスデーモンに食われる必要があります。
イベント後3年でジャンプして申し訳ありませんが、注意事項はこちら...
最後の大きなプロジェクトでは、私の中心的なデータ構造はかなり単純なオブジェクトのセットでした。プロジェクトが開始されて約1年が経ち、要件が進化するにつれて、オブジェクトは実際にはポリモーフィックである必要があることに気付きました。データ構造を基本クラスポインターのセットに修正し、オブジェクトストレージ、キャストなどの付随的な損傷をすべて処理するには、数週間の困難で厄介な脳手術が必要でした。新しいコードが機能していることを確信させるのに数ヶ月かかりました。ちなみに、これにより、C ++のオブジェクトモデルがどれほど適切に設計されているかを考えるようになりました。
現在の大規模プロジェクトでは、中心的なデータ構造はかなり単純なオブジェクトのセットです。プロジェクトに約1年かかった(たまたま今日だった)が、オブジェクトは実際にはポリモーフィックである必要があることに気付いた。ネットに戻り、このスレッドを見つけ、ニックのBoostポインターコンテナライブラリへのリンクを見つけました。これは、すべてを修正するために前回書いたものとまったく同じなので、今回はやってみます。
道徳、私にとっては、とにかく:もしあなたの仕様が100%石にキャストされていないなら、ポインタを探してください。
両方の利点を最大限に活用しない理由:スマートポインターのコンテナーを作成する( boost::shared_ptr
または std::shared_ptr
)。メモリを管理する必要はなく、大規模なコピー操作に対処する必要もありません。
オブジェクトをSTLコンテナに直接保存するのが最も簡単で、最も簡単で効率的で、オブジェクトを使用するのが最も簡単です。
オブジェクト自体にコピーできない構文がある場合、または抽象基本型の場合は、ポインターを保存する必要があります(最も簡単なのはshared_ptrを使用することです)
違いをよく把握しているようです。オブジェクトが小さくてコピーしやすい場合は、必ず保存してください。
そうでない場合、ヒープに割り当てるものへのスマートポインター(refをカウントするrefのスマートポインターではない)を保存することを考えます。明らかに、スマートポインターを選択した場合、一時スタックに割り当てられたオブジェクトを格納することはできません(前述したとおり)。
@ Torbj <!> #246; rn はスライスについて良い点を示しています。
コンテナはオブジェクト全体ではなくポインタのみをコピーするため、ポインタの使用はより効率的です。
STLコンテナとスマートポインターに関する有用な情報がここにあります:
なぜstdを使用するのが間違っているのか:: auto_ptr <!> lt; <!> gt;標準コンテナを使用する場合
オブジェクトをコードの他の場所で参照する場合は、boost :: shared_ptrのベクターに格納します。これにより、ベクトルのサイズを変更しても、オブジェクトへのポインターが有効のままになります。
つまり:
std::vector<boost::shared_ptr<protocol> > protocols;
...
connection c(protocols[0].get()); // pointer to protocol stays valid even if resized
他の誰もオブジェクトへのポインタを保存しない場合、またはリストが拡大および縮小しない場合は、単純に古いオブジェクトとして保存します。
std::vector<protocol> protocols;
connection c(protocols[0]); // value-semantics, takes a copy of the protocol
この質問はしばらくの間私を悩ませてきました。
私はポインターを保存することに傾いていますが、あなたには当てはまらないかもしれない追加の要件(SWIG luaラッパー)があります。
この投稿で最も重要な点は、あなたのオブジェクト
を使用して、自分でテストすることです。今日、これを実行して、500万回、1000万個のオブジェクトのコレクションでメンバー関数を呼び出す速度をテストしました。
この関数は、xdirとydir(すべてのfloatメンバー変数)に基づいてxとyを更新します。
両方のタイプのオブジェクトを保持するためにstd :: listを使用しましたが、リストにオブジェクトを保存する方がポインターを使用するよりもわずかに速いことがわかりました。一方、パフォーマンスは非常に近いため、アプリケーションでの使用方法に依存します。
参考までに、ハードウェアで-O3を使用すると、ポインターの完了には41秒かかり、生のオブジェクトの完了には30秒かかりました。