160

私はいくつかの記事を読んで、生のポインターはほとんど使用されるべきではないということを読みました。代わりに、スコープポインターであろうと共有ポインターであろうと、常にスマートポインター内にラップする必要があります。

ただし、Qt、wxWidgetsなどのフレームワーク、およびBoostなどのライブラリは、スマートポインターをまったく使用していないかのように、それらを返さず、期待しないことに気付きました。代わりに、生のポインターを返すか、期待します。その理由はありますか?パブリックAPIを作成するときは、スマートポインターを使用しないようにする必要がありますか?その理由は何ですか?

多くの主要なプロジェクトがスマートポインターを避けているように見えるのに、なぜスマートポインターが推奨されるのか疑問に思っています。

4

8 に答える 8

124

標準のスマート ポインターが登場する前に多くのライブラリが作成されたという事実は別として、おそらく最大の理由は、標準の C++ アプリケーション バイナリ インターフェイス (ABI) がないことです。

ヘッダーのみのライブラリを作成している場合は、スマート ポインターと標準コンテナーを心ゆくまで渡すことができます。それらのソースはコンパイル時にライブラリで利用できるため、実装ではなく、インターフェイスの安定性のみに依存します。

ただし、標準の ABI がないため、通常、これらのオブジェクトをモジュールの境界を越えて安全に渡すことはできません。GCCshared_ptrはおそらく MSVC とは異なり、MSVCshared_ptrも Intel とは異なる可能性がありますshared_ptr同じコンパイラを使用しても、これらのクラスはバージョン間でバイナリ互換性があるとは限りません。

肝心なのは、ライブラリのビルド済みバージョンを配布する場合は、依存する標準 ABI が必要だということです。C にはありませんが、コンパイラ ベンダーは、特定のプラットフォームの C ライブラリ間の相互運用性について非常に優れています。デファクト スタンダードがあります。

C++ の場合、状況はそれほど良くありません。個々のコンパイラは独自のバイナリ間の相互運用を処理できるため、サポートされているすべてのコンパイラ (多くの場合 GCC と MSVC) のバージョンを配布するオプションがあります。しかし、これを考慮すると、ほとんどのライブラリは C インターフェイスをエクスポートするだけです。つまり、生のポインターを意味します。

ただし、非ライブラリ コードは通常、raw よりもスマート ポインターを優先する必要があります。

于 2012-04-26T22:28:32.333 に答える
39

多くの理由が考えられます。それらのいくつかをリストするには:

  1. スマート ポインターは、つい最近標準の一部になりました。それまでは他のライブラリの一部でした
  2. それらの主な用途は、メモリ リークを回避することです。多くのライブラリには独自のメモリ管理がありません。一般に、ユーティリティと API を提供します。
  3. これらは実際にはオブジェクトでありポインターではないため、ラッパーとして実装されます。生のポインターと比較して、追加の時間/空間コストがあります。ライブラリのユーザーは、そのようなオーバーヘッドを望んでいない場合があります。

編集: スマート ポインターの使用は、完全に開発者の選択です。それはさまざまな要因に依存します。

  1. パフォーマンスが重要なシステムでは、オーバーヘッドを生成するスマート ポインターを使用したくない場合があります。

  2. 下位互換性が必要なプロジェクトでは、C++11 固有の機能を持つスマート ポインターを使用したくない場合があります。

Edit2以下のパッセージのため、24 時間の間にいくつかの反対票が連続して発生しています。以下は単なるアドオンの提案であり、回答ではないにもかかわらず、回答が反対票を投じられた理由を理解できません。
ただし、C++ では常にオプションを開くことが容易になります。:) 例えば

template<typename T>
struct Pointer {
#ifdef <Cpp11>
  typedef std::unique_ptr<T> type;
#else
  typedef T* type;
#endif
};

コードでは次のように使用します。

Pointer<int>::type p;

スマート ポインターと生のポインターは違うと言う人には、私も同意します。上記のコードは、単に a と交換可能なコードを記述できるアイデア#defineにすぎません。これは強制ではありません。

たとえば、T*明示的に削除する必要がありますが、スマート ポインターは削除しません。それを処理するためのテンプレートを用意できますDestroy()

template<typename T>
void Destroy (T* p)
{
  delete p;
}
template<typename T>
void Destroy (std::unique_ptr<T> p)
{
  // do nothing
}

そしてそれを次のように使用します:

Destroy(p);

同様に、生のポインターの場合は直接コピーでき、スマート ポインターの場合は特別な操作を使用できます。

Pointer<X>::type p = new X;
Pointer<X>::type p2(Assign(p));

どこAssign()にあります:

template<typename T>
T* Assign (T *p)
{
  return p;
}
template<typename T>
... Assign (SmartPointer<T> &p)
{
  // use move sematics or whateve appropriate
}
于 2012-04-26T13:37:54.163 に答える
35

スマートポインタ(C ++ 11より前)には2つの問題があります。

  • 非標準であるため、各ライブラリは独自のライブラリを再発明する傾向があります(NIH症候群と依存関係の問題)
  • 潜在的なコスト

コストがかからないという点で、デフォルトのスマートポインタはですunique_ptr。残念ながら、C ++ 11の移動セマンティクスが必要ですが、これは最近登場したばかりです。他のすべてのスマートポインタには、コスト(shared_ptrintrusive_ptr)があるか、理想的ではないセマンティクス(auto_ptr)があります。

C ++ 11std::unique_ptrが間近に迫っていると、ついに終わったと思いたくなるでしょう...私はそれほど楽観的ではありません。

C ++ 11のほとんどを実装している主要なコンパイラはごくわずかであり、最近のバージョンでのみ実装されています。QTやBoostなどの主要なライブラリは、しばらくの間C ++ 03との互換性を維持することをいとわないことが予想されます。これにより、新しくて光沢のあるスマートポインタを広く採用することができなくなります。

于 2012-04-26T13:50:42.643 に答える
13

スマート ポインターから離れてはいけません。スマート ポインターは、特にオブジェクトを渡す必要があるアプリケーションで使用されます。

ライブラリは、単に値を返すか、オブジェクトを設定する傾向があります。通常、多くの場所で使用する必要のあるオブジェクトを持っていないため、スマート ポインターを使用する必要はありません (少なくともインターフェイスではなく、内部で使用する可能性があります)。

私たちが取り組んできたライブラリを例にとると、数か月の開発の後、ポインタとスマート ポインタをいくつかのクラス (全クラスの 3 ~ 5%) でしか使用していないことに気付きました。

ほとんどの場合、参照による変数の受け渡しで十分でした。null になる可能性のあるオブジェクトがある場合は常にスマート ポインターを使用し、使用するライブラリによって強制された場合は生のポインターを使用しました。

編集(私の評判のためコメントできません): 参照による変数の受け渡しは非常に柔軟です: オブジェクトを読み取り専用にしたい場合は、const 参照を使用できます (オブジェクトを書き込むために厄介なキャストを行うこともできます) ) しかし、可能な限り最大限の保護を得ることができます (スマート ポインターと同じです)。しかし、オブジェクトを返すだけの方がはるかに優れていることに同意します。

于 2012-04-26T13:59:05.810 に答える
8

Qt は Java になろうとして、標準ライブラリの多くの部分を無意味に再発明しました。現在、実際には独自のスマートポインターがあると思いますが、一般的に、設計の頂点とは言えません. 私の知る限り、wxWidgets は、使用可能なスマート ポインターが作成されるずっと前に設計されました。

Boostに関しては、適切な場所でスマートポインタを使用することを完全に期待しています. もっと具体的にする必要があるかもしれません。

さらに、所有権を強制するためのスマート ポインターが存在することを忘れないでください。API に所有権のセマンティクスがない場合、なぜスマート ポインターを使用するのでしょうか?

于 2012-04-26T13:41:53.853 に答える
3

良い質問。あなたが参照している具体的な記事はわかりませんが、私は時々同じようなことを読んでいます。私の疑惑は、そのような記事の執筆者は、C++スタイルのプログラミングに対して偏見を抱く傾向があるということです。ライターが必要なときにだけC++でプログラムし、Javaなどにできるだけ早く戻る場合、C++の考え方を実際に共有することはありません。

同じライターの一部またはほとんどがガベージコレクションメモリマネージャーを好むのではないかと疑われています。私はしませんが、彼らとは違った考え方をします。

スマートポインタは素晴らしいですが、参照カウントを維持する必要があります。参照カウントを維持することは、実行時にコスト(多くの場合、適度なコストですが、それでもコスト)を負担します。特にポインタがデストラクタによって管理されている場合は、ベアポインタを使用してこれらのコストを節約することに何の問題もありません。

C ++の優れた点の1つは、組み込みシステムプログラミングのサポートです。ベアポインタの使用はその一部です。

更新: コメント投稿者は、C ++の新しいunique_ptr(TR1以降で使用可能)が参照をカウントしないことを正しく観察しました。コメント投稿者はまた、私が考えているのとは異なる「スマートポインタ」の定義を持っています。彼はその定義について正しいかもしれません。

さらなる更新: 以下のコメントスレッドが光っています。それはすべて読むことをお勧めします。

于 2012-04-26T13:39:47.347 に答える
0

それはまた、あなたがどの分野で働いているかにもよります。私は生計を立てるためにゲーム エンジンを書いています。私たちのコア エンジンでは、独自のバージョンの stl (ea stl によく似ています) を作成することになりました。

フォーム アプリケーションを作成する場合、スマート ポインターの使用を検討するかもしれません。しかし、メモリ管理が第二の性質になると、メモリをきめ細かく制御できないと、静かに煩わしくなります。

于 2013-01-08T02:06:43.040 に答える