問題タブ [ownership-semantics]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - スマート ポインター: オブジェクトの所有者は?
C++ はメモリの所有権、つまり所有権のセマンティクスがすべてです。
そのメモリを解放するのは、動的に割り当てられたメモリのチャンクの所有者の責任です。したがって、問題は本当に誰がメモリを所有するかになります。
C++ では、所有権は生のポインターが内部でラップされる型によって文書化されているため、優れた (IMO) C++ プログラムでは、生のポインターが渡されるのを見ることは非常にまれです (まれではありません)。誰がメモリを所有しているのかわからないため、ドキュメントを注意深く読まなければ、誰が所有権を持っているのかわかりません)。
逆に、生のポインターがクラスに格納されることはほとんどありません。各生のポインターは、独自のスマート ポインター ラッパー内に格納されます。(注:オブジェクトを所有していない場合は、オブジェクトを保存するべきではありません。オブジェクトがいつスコープから外れて破棄されるかがわからないためです。)
だから質問:
- 人々が遭遇した所有権のセマンティックのタイプは何ですか?
- これらのセマンティクスを実装するために使用される標準クラスは何ですか?
- どのような状況でそれらが役立つと思いますか?
回答ごとに 1 種類のセマンティック オーナーシップを保持して、個別に投票できるようにします。
概要:
概念的には、スマート ポインターは単純であり、単純な実装は簡単です。私は多くの試みられた実装を見てきましたが、それらは常に何らかの方法で壊れており、カジュアルな使用や例では明らかではありません. したがって、独自のスマート ポインターを展開するのではなく、ライブラリから十分にテストされたスマート ポインターを常に使用することをお勧めします。std::auto_ptr
または、Boost スマート ポインターの 1 つが私のニーズをすべてカバーしているようです。
std::auto_ptr<T>
:
1 人の人物がオブジェクトを所有しています。所有権の譲渡は許可されています。
使用法: これにより、所有権の明示的な譲渡を示すインターフェイスを定義できます。
boost::scoped_ptr<T>
1 人の人物がオブジェクトを所有しています。所有権の譲渡は許可されていません。
使用法: 明示的な所有権を示すために使用されます。オブジェクトは、デストラクタによって、または明示的にリセットされたときに破棄されます。
boost::shared_ptr<T>
( std::tr1::shared_ptr<T>
)
複数所有。これは単純な参照カウント ポインターです。参照カウントがゼロになると、オブジェクトは破棄されます。
使用法: オブジェクトが、コンパイル時に決定できない有効期間を持つ複数の権限を持つことができる場合。
boost::weak_ptr<T>
:
shared_ptr<T>
ポインターのサイクルが発生する可能性がある状況で使用されます。
使用法: サイクルのみが共有参照カウントを維持している場合に、サイクルがオブジェクトを保持するのを停止するために使用されます。
c++ - デストラクタでメンバーを削除しないようにするにはどうすればよいですか?
クラスのデストラクタで、他の場所で削除されたメンバーの 1 つを除いて、オブジェクト全体を削除したいと思います。まず、これはまったく理不尽ですか?そうでないと仮定すると、どうすればこれを行うことができますか?空のボディでデストラクタを作成すると、すべてのメンバーが削除されるのを防ぐことができると思いました(デストラクタは何もしないため)が、そうではないようです。
c++ - Boost ライブラリのスマート ポインタを使用してオブジェクトの有効期間を管理するにはどうすればよいですか?
shared_ptr および weak_ptr スマート ポインターで解決する必要があるシナリオがあります。
スレッド 1 とスレッド 2 の 2 つのスレッドは、A という共有オブジェクトを使用しています。各スレッドは、そのオブジェクトへの参照を持っています。スレッド 1 はオブジェクト A を削除することを決定しますが、同時にスレッド 2 がそれを使用している可能性があります。各スレッドでオブジェクト A の参照を保持するために shared_ptr を使用した場合、オブジェクトは適切なタイミングで削除されません。
オブジェクトを削除する必要があるときにオブジェクトを削除し、そのオブジェクトを同時に使用している他のスレッドでエラーが発生しないようにするにはどうすればよいですか?
c++ - 所有権セマンティクスのような生のポインタに対してunique_ptrを返すのは悪い習慣ですか?
別のデータ オブジェクトから取り込まれた新しい Foobar オブジェクトを返す静的ファクトリ メソッドを作成しました。私は最近、所有権のセマンティクスに夢中になっており、このファクトリ メソッドにunique_ptr
.
私の意図は、ポインターを所有していることをクライアント コードに伝えることです。スマート ポインターがなければ、単純に を返しFoobar*
ます。ただし、潜在的なバグを回避するためにこのメモリを強制的に削除したいのでunique_ptr
、適切な解決策のように思えました. クライアントがポインターの有効期間を延長したい場合は.release()
、unique_ptr
.
私の質問は2つの部分に分かれています:
- このアプローチは正しい所有権のセマンティクスを伝えていますか?
unique_ptr
これは、生のポインターの代わりに返す「悪い習慣」ですか?
qt - QActionの所有権
QAction* オブジェクトを削除する責任がある QMenu に QAction* を追加するときは? QMenu または QAction のドキュメントで言及されているのを見つけることができませんでした。
Qt Menusの例では、作成したアクションは削除されないため、QMenu が QAction の所有権を取得すると仮定します。あれは正しいですか?
c++ - 新しい Unique_ptrs の所有権は?
最近の就職面接での提案によると、自動化されたガベージ コレクションの手段として、C++11 の unique_ptr 機能を調査するように勧められました。だから私は古いプロジェクトを使用しており、「new」キーワードで作成されたオブジェクトへの生のポインタをunique_ptrsに置き換えています。しかし、私は所有権の問題に到達したと思います。
私の mainclass.cpp (以下に掲載) で、init 関数と、私が作成した新しくインスタンス化されたオブジェクトへの 3 つの unique_ptrs に注目してください。「bg」、「bg2」、および「theGrid」と名付けられました。(その下のコメントアウトされた宣言は、以前の方法であり、この方法に戻すと、プログラムは問題なく実行されます。)
ただし、unique_ptrs を使用すると、関数 void display() の行は次のようになります。
アクセス違反を発生させます。これは、指定されたオブジェクトのいずれかが逆参照されるシーケンスの中で初めてでもあり、unique_ptr の所有権がすでにどこかで失われていると思われます。ただし、unique_ptrs 自体は別の関数やコンテナーに渡されることはなく、mainclass.cpp のスコープ内にとどまるため、必要な場所に所有権を譲渡するために std::move(theGrid) を使用する機会はありません。することが。
Mainclass.cpp:
ある時点で所有権を譲渡する必要があると思いますが、どこにあるのかわかりません。
前もってありがとう、ガイ
c++ - Delphi で所有権を明示的に表現する
私は主に C++ プログラマーであり、オブジェクトの所有権を表すためstd::unique_ptr
に、 などのクラス テンプレートを使用することに慣れてきました。std::shared_ptr
Delphi の標準ライブラリには、類似したものがありますか? コードを書くときに従うべき、オブジェクトの所有権を表現するためのベストプラクティスはありますか?
編集: C++11 が標準になったため、2 つの軽量ヘルパー クラスstd::shared_ptr
とstd::unique_ptr
.
type の変数を作成するとstd::shared_ptr<int>
、それは共有所有権を持つ int へのポインターを表します。フードの下では参照カウントが行われ、ref-count がゼロに達すると、ポインターは自動的に解放されます。このタイプは一種の「共有所有権」を表しており、多くのオブジェクトがリソースを使い終わったときにそのリソースを破棄する責任を共有しています。
対照的に、std::unique_ptr
単一の所有権を表します。unique_ptr が範囲外になると、リソースは自動的に解放されます。std::unique_ptr はコピーできません。一度にこのリソースを所有するオブジェクトが 1 つだけ存在する可能性があり、オブジェクトのクリーンアップを担当するオブジェクトが 1 つだけ存在します。
これらの軽量クラスを int へのネイキッド ポインターと対比してください。共有所有権、一意の所有権、または別の場所のオブジェクトへの参照を表すことができます。タイプは何も教えてくれません。
私の質問は次のとおりです。Delphi はオブジェクトへの参照の保持をサポートしているため、「私はこのオブジェクトの唯一の所有者です。処理が完了したら解放します」と明示的に述べるメカニズムはありますか?相互作用の目的でこのオブジェクトを参照しますが、他の誰かがそれをクリーンアップします" vs "私はこのオブジェクトを他の多くのオブジェクトと共有しており、最後にそれを持っている人は誰でもそれをクリーンアップできます."
TList
Collections.Generics にはvsなどのさまざまなコレクションがTObjectList
あり、TObjectList はその中に格納されているメンバーを解放しますが、TList は解放しません。TObjectList はその要素を「所有」しているのに対し、TList は所有していないと言えます。これが私の質問の本質です。独自のクラスを設計する場合、この種の所有権の問題を言語内で直接表現する方法はありますか? または、開発者の間で一般的なベスト プラクティスや命名規則はありますか?