33

boost::shared_ptr などのスマート ポインターを返すときのベスト プラクティスは何ですか? 標準でスマート ポインターまたは基になる生のポインターを返す必要がありますか? 私は C# 出身なので、常にスマート ポインターを返す傾向があります。このように (短いコードの const-correctness をスキップします):

class X
{
public:
    boost::shared_ptr<Y> getInternal() {return m_internal;}

private:
    boost::shared_ptr<Y> m_internal;
}

ただし、生のポインターを返し、生のポインターをベクトルに入れる経験豊富なコーダーを見てきました。それを行う正しい方法は何ですか?

4

9 に答える 9

24

「正しい」方法はありません。それは本当に文脈に依存します。

スマート ポインターを使用してメモリを内部的に処理し、参照または生のポインターを外部的に与えることができます。結局のところ、インターフェイスのユーザーは、内部でメモリがどのように管理されているかを知る必要はありません。同期コンテキストでは、これは安全で効率的です。非同期コンテキストには、多くの落とし穴があります。

何をすべきかわからない場合は、呼び出し元にスマート ポインターを安全に返すことができます。参照カウントがゼロになると、オブジェクトの割り当てが解除されます。オブジェクトのスマートポインターを永久に保持するクラスがないことを確認してください。これにより、必要なときに割り当て解除が妨げられます。

最後に、C++ では動的に割り当てられたオブジェクトを過度に使用しないでください。ポインターを必要とせず、参照と const 参照で作業できる場合が多くあります。これはより安全であり、メモリ アロケータへの負担を軽減します。

于 2009-06-10T11:23:30.613 に答える
11

ポインタの意味によって異なります。

shared_pointer を返すときは、構文的に「このオブジェクトの所有権を共有する」ことを意味します。つまり、ポインターを解放する前に元のコンテナー オブジェクトが停止した場合でも、そのオブジェクトは引き続き存在します。

生のポインターを返すと、「このオブジェクトについて知っているが、所有していない」ということになります。これはコントロールを渡す方法ですが、ライフタイムを元の所有者に結び付けたままにするわけではありません。

(一部の古い C プログラムでは、「私を削除するのはあなたの問題です」という意味ですが、これを避けることを強くお勧めします)

通常、共有をデフォルトにすると多くの手間が省けますが、それは設計次第です。

于 2009-06-10T11:26:44.600 に答える
8

ポインター引数を関数に渡し、ポインターを返すには、次のガイドラインに従います。

boost::shared_ptr

API とクライアントは、このオブジェクトの所有権を共有しています。shared_ptrただし、オブジェクトが何らかのグラフを表している場合は、 での循環参照を避けるように注意する必要があります。shared_ptrこのため、私は の使用を制限しようとしています。

boost::weak_ptr / raw pointer

API がこのオブジェクトを所有しているため、有効な間は共有できます。クライアントが API よりも長く存続する可能性がある場合は、weak_ptr を使用します。

std::auto_ptr

API はオブジェクトを作成していますが、クライアントがオブジェクトを所有しています。これにより、戻りコードが例外セーフであることが保証され、所有権が譲渡されていることが明確に示されます。

boost::scoped_ptr

スタックに格納されたオブジェクトへのポインタ、またはクラス メンバ変数として。まずは使ってみますscoped_ptr

すべてのガイドラインと同様に、ルールが矛盾したり、曲げなければならない場合があるため、私は知性を活用しようとします。

于 2009-06-10T12:54:09.697 に答える
7

私は通常、工場などから「所有」/「一意」のスマート ポインターを返し、クリーンアップの責任者を明確にします。

この例https://ideone.com/qJnzvastd::unique_ptrは、呼び出し元が値を割り当てる変数のスコープがスコープ外になったときに削除されるを返す方法を示しています。

スマート ポインターがそれ自体のポインターを削除するのは事実ですが、スマート ポインターを保持する変数の有効期間は呼び出し元によって 100% 制御されるため、呼び出し元はポインターがいつ削除されるかを決定します。ただし、これは「一意」で「所有する」スマート ポインターであるため、他のクライアントが有効期間を制御することはできません。

于 2009-06-10T12:02:14.637 に答える
4

生のポインターを返すことは決してありません。代わりに、weak_ptr を返して、ユーザーがリソースを制御できないことをポインターのユーザーに伝えます。

もしweak_ptrを返した場合、アプリケーションにダングリングポインタが存在する可能性は非常に低いです.

パフォーマンスの問題がある場合は、オブジェクトへの参照と hasValidXObject メソッドを返します。

于 2009-06-10T11:45:31.083 に答える
3

私の意見では、C++ では、無防備なポインターの使用を常に正当化する必要があります。

多くの正当な理由が考えられます。非常に高いパフォーマンスが必要な場合、メモリ使用量が非常に少ない場合、レガシー ライブラリを処理する必要がある場合、ポインタが格納している基本的なデータ構造に何らかの問題がある場合などです。しかし、[動的に割り当てられた] ポインターは、可能なすべての実行パスでメモリの割り当てを解除する必要があり、ほぼ確実に 1 つを忘れるという点で、やや「悪」です。

于 2009-06-10T11:17:23.777 に答える
0

あなたの目標に依存します。

やみくもにスマート ptr を内部データに返すのは良い考えではないかもしれません (解決しようとしているタスクに非常に敏感です)。 .

一方、スマート ptr を返す場合は、オブジェクトが互いに破壊できなくなったときに相互循環参照を作成しないことも考慮する必要があります (その場合は、weak_ptr の方が適している可能性があります)。

それ以外の場合は、前述のように、パフォーマンス/レガシー コード/ライフタイムに関する考慮事項をすべて考慮する必要があります。

于 2009-06-10T11:22:21.473 に答える
0

生のポインタをベクトルに入れません。

auto_ptr または boost::scoped_ptr を使用する場合、生のポインター以外は使用 (または返す) できません。それは彼らのコーディング方法を説明できると思います。

于 2009-06-10T11:22:39.053 に答える
-2

const boost::shared_ptr &getInternal() {return m_internal;}

これにより、コピーが回避されます。

参照を返したい場合があります。たとえば、次のようになります。

  • Y &operator*() { return *m_internal; }
  • const Y &operator*() const { return *m_internal; }

これも、参照が使用されてすぐに破棄される場合にのみ有効です。同じことが生のポインターにも当てはまります。weak_ptr を返すこともオプションです。

目的によっては4つが良いです。この質問には、より広範な議論が必要です。

于 2009-06-11T13:36:58.733 に答える