スマートポインターを使用するかどうか。ライブラリに渡すすべてのポインタがライブラリによって所有されている必要があることをライブラリのユーザーに明示したいと思います(つまり、ユーザーによって解放されません)。
多くのオープンソース ライブラリは、ライブラリがすべてを所有しているかどうかをドキュメントに記載しています。彼らは、渡されるポインターの予想される寿命について議論しています。確かに、この情報をユーザーに伝えるためのより厳密な方法があります。
例は素晴らしいでしょう。
ありがとう!
スマートポインターを使用するかどうか。ライブラリに渡すすべてのポインタがライブラリによって所有されている必要があることをライブラリのユーザーに明示したいと思います(つまり、ユーザーによって解放されません)。
多くのオープンソース ライブラリは、ライブラリがすべてを所有しているかどうかをドキュメントに記載しています。彼らは、渡されるポインターの予想される寿命について議論しています。確かに、この情報をユーザーに伝えるためのより厳密な方法があります。
例は素晴らしいでしょう。
ありがとう!
本当にそれが必要な場合は、ユーザーに割り当てさせるのではなく、これらのオブジェクトを作成するメソッドもライブラリに提供する必要があります。両方が同じ割り当て機能を使用することを保証できないため、ライブラリが作成していないオブジェクトを解放することは意味がありません。
ライブラリがこれらのオブジェクトを作成し、ポインターを隠して外部クライアントがラップされたオブジェクトを解放できないようにするカスタム スマート ポインターにラップするオプションがありますが、ガードを回避することは常に可能です。私の経験では、賢くなりすぎると常に裏目に出ます。物事はより複雑になりますが、ライブラリを使用する開発者は常にそれを裏切ることができます。
IMO によると、最も安全なアプローチは、単純なライフサイクル管理 API (CreateObject、DestroyObject など) と明確で簡潔なドキュメントです。その後、ユーザーはライフタイムの処理方法を自由に選択できます (例:カスタム デリーターを使用するshared_ptr
か、まったく別のものを使用する)。unique_ptr
DestroyObject
すべてのクラスで所有スマート ポインターを使用します。所有スマート ポインターは所有権を取得し (つまり、一度オブジェクトを処理するとオブジェクトを破棄します)、ユーザーから渡されたすべてのポインターは、この所有スマート ポインターによって引き継がれます。
良い例はstd::unique_ptr
、物事が完了すると、そのオブジェクトを破棄することです。
カスタムの破棄が必要な場合は、カスタムのデリータを渡すことができます。
もちろん、両方の作成 (つまり をmake_unique
使用) もクラスに含めることをお勧めします。RAII を使用すると、すべてのリークが回避されます。
これを行う 1 つの方法は、new/delete演算子をオーバーロードし、それらの関数を使用してアクセスをフィルター処理することです。たとえば、 new はオブジェクトを作成し、アドレスをプライベートな静的データ構造に格納します。delete object
Delete は、特定の条件が満たされない限り、イディオムを使用しようとする試みをブロックするように設計できます。
ライブラリ関数、メソッド、およびコンストラクターを値で受け取るように記述した場合、引数の移動コピー時にインスタンスがクリアされるstd::unique_ptr<T>
ため、ユーザーがポインター自体を解放する方法はありません。unique_ptr
class C;
void library_function(std::unique_ptr<C> by_value);
void user_code() {
std::unique_ptr<C> user_c{std::make_unique<C>("param", 5)};
library_function(user_c);
assert(user_c.get() == nullptr);
}
ユーザーが引き続きオブジェクトを監視できるようにする必要がある場合はshared_ptr
、インターフェイスで受け入れるか、生の (所有していない) ポインターまたは (より良い) 参照を返すオブザーバー メソッドを提供できます。