9

私はデータ構造クラスを取っています。教授のすべての例で、教授は、構造またはコンテナ自体を保持するのではなく、常にマップに構造またはコンテナへのポインタの値を持たせています。

彼はそれを習慣としてやっているだけなのか、それとも速度が上がるなどの正当な理由があるのでしょうか。

  • データへのポインターを使用して、データの冗長なコピーを回避しながら、同時に複数のコンテナー/構造にそのデータへの方向を格納できることを認識しています。
  • これらの例では、そうではありません。データはそのマップにのみあります。
4

3 に答える 3

11

私が見ているように、ポインタとオブジェクトのどちらを使用するかを決定する際には、いくつかの要因が関係しています。

1.ポリモーフィズムが必要ですか、それとも必要ありませんか?

基本クラスオブジェクトのコンテナを維持し、その中にさまざまな派生クラスのオブジェクトを格納する場合は、仮想関数呼び出しが正しく解決されないため、ポインタを使用する必要があります。

2.保存するオブジェクトのサイズとコピー操作への適合性

ポインタがオブジェクトよりも優先される主な理由の1つは、コンテナで実行されるさまざまな操作に、コンテナに格納されているオブジェクトのコピーの作成が含まれることです。これは、多くの格納操作(例std::vector<>::push_back()、またはstd::map<>::insert())、一部の取得操作(例std::vector<>::operator[]、およびオブジェクトをローカル変数に格納する)、およびコンテナによって「内部的に」実行される操作の一部(たとえば、再割り当て)の場合です。容量を超えて成長したときのベクトル、またはの再ハッシュstd::unordered_map<>。コンテナの選択方法とその使用方法によっては、コピー操作の重要性が低くなる場合があることに注意してください(たとえばstd::vector<>::reserve()、十分なスペースの割り当てstd::vector<>::emplace_back()、ストレージの使用、取得した要素のローカルコピーを作成しない場合は、コピーがないことを意味する場合があります)。これまでに作られた)。

ただし、多数のコピーが作成されることが予想される場合(または、既存のコードをプロファイリングすると多くのコピーが作成されることが判明した場合)、ポインターは小さく、メモリ内で適切に配置されているため、オブジェクトの代わりにポインターを使用すると明らかに役立ちます。繰り返しになりますが、格納するオブジェクトが実際にポインタよりも小さい場合、これはあまり意味がありません。

3.コンテナとその内容に対して実行するその他の操作

扱っているオブジェクトがポインターよりも大きく、大量のコピー操作が予想される場合でも、ポインターの使用は必ずしも好ましいとは限りません。多数の中型オブジェクト(たとえば、それぞれ16バイト)を格納し、コンテナー全体を繰り返し処理して、ある種の統計計算を実行する必要がある状況を考えてみます。これらのオブジェクトをベクトルに直接格納すると、反復中に優れたキャッシュ効率が得られます。1つのオブジェクトを取得すると、キャッシュライン全体がメモリから取得されるため、次のいくつかのオブジェクトの取得がはるかに高速になります。これは通常、ポインタが使用されている場合には当てはまりません。逆に、要素を取得した後は、ポインタを逆参照する必要があり、キャッシュされていない可能性のあるメモリ領域から別の移動操作が発生します。

明らかに、それはすべて、保存するオブジェクトのタイプとサイズ、および実行する操作のタイプと頻度に依存します。扱っているオブジェクトがGUIアプリケーションのさまざまなタイプのウィンドウ、ボタン、およびメニューである場合は、ポインターを使用してポリモーフィズムを利用することをお勧めします。一方、サイズと形状がすべて同じであるコンパクトな要素の巨大な構造を扱っている場合、実行する操作に頻繁な反復または一括コピーが含まれる場合は、オブジェクトを直接保存することをお勧めします。また、両方を試し、メモリと時間のベンチマークの結果に基づいて決定しないと、決定を下すのが難しい場合もあります。


最後に、ポインタを使用することになった場合は、構築しているコンテナが、ヒープに割り当てているオブジェクトの最終的な所有者であるか、一時的なポインタを維持しているだけであるかを検討してください。コンテナがこれらのオブジェクトの所有者である場合は、生のポインタではなく、スマートポインタを使用することをお勧めします。

于 2012-09-17T01:56:56.320 に答える
2

オブジェクトインスタンスをコンテナに直接格納することの利点は、あるレベルの間接参照を回避し、ポインタ自体が使用するスペースを節約できることです。ポインタを格納する代わりにオブジェクトインスタンスを直接格納することで、時間とスペースの両方の効率の面で勝つことができます。プロセッサキャッシュメモリがどのように機能するかを少し理解していれば、オブジェクトインスタンスをコンテナに「インライン」で格納することで実際のパフォーマンスがどのように向上するかを理解するのは難しくありません。

含まれているタイプやコンテナーの使用パターンについて何も仮定しない場合、デフォルトのコンテナーはstd::vector<T>(ではなくstd::vector<T*>)である必要があります。そのデフォルトの選択から始めて、使用パターンが他のタイプの構造のパフォーマンスプロファイルからどのように利益を得るかを確認できる場合は、ベクトル以外のものを使用します。同様に、ポインターの間接参照が必要であるか、パフォーマンスの観点から価値があると思われる場合は、コンテナーにオブジェクトへのポインターを格納します。含まれている型がコピー構築可能でない場合は間接参照が必要であり、コンテナーがそのオブジェクトを「所有」していない場合にも必要です。

于 2012-09-17T01:56:34.980 に答える
1

1つの可能性は、コンテンツタイプがコピーできないことです。

于 2012-09-17T00:52:44.203 に答える