私はC ++にかなり慣れていません。shared_ptr
別の参照カウンター変数への別のポインターを保持していると考えられていました。しかし、今日、実際にはどのようにレイアウトされているのかわからないことに突然気付きました.C ++では、参照値はポインターを分離する必要はありません。
レイアウトが標準で定義されている場合、正しい予想されるレイアウトはstd::shared_ptr
何ですか?
私はC ++にかなり慣れていません。shared_ptr
別の参照カウンター変数への別のポインターを保持していると考えられていました。しかし、今日、実際にはどのようにレイアウトされているのかわからないことに突然気付きました.C ++では、参照値はポインターを分離する必要はありません。
レイアウトが標準で定義されている場合、正しい予想されるレイアウトはstd::shared_ptr
何ですか?
C++ 標準では、非標準レイアウト クラスのメモリ内での配置方法を定義していません (例: [class.mem]/13)。
同じアクセス制御 (条項 11) を持つ (非共用体) クラスの非静的データ メンバーは、後のメンバーがクラス オブジェクト内でより高いアドレスを持つように割り当てられます。アクセス制御が異なる非静的データメンバーの割り当て順序は規定されていません (第 11 節)。実装のアライメント要件により、隣接する 2 つのメンバーが互いの直後に割り当てられない場合があります。仮想関数 (10.3) および仮想基本クラス (10.1) を管理するためのスペースの要件も同様です。
標準レイアウト タイプにはいくつかの例外/簡略化がありますが、クラスのメモリ レイアウトに関する一般的な仕様はありません。
これは、標準ライブラリのクラスにも当てはまります。それに加えて、標準はこれらのクラスの要件のみを定義しています。それらのいくつかは、メンバー関数のシグネチャという意味での「インターフェース」です。[objects.within.classes] で非常に明示的に:
1) 条項 18 から 30 および付属書 D [つまり、標準ライブラリ] は、クラスの表現を指定しておらず、意図的にクラス メンバーの指定を省略しています (9.2)。実装は、条項 18 から 30 および附属書 D で指定されたメンバー関数のセマンティクスを実装するために必要に応じて、静的または非静的クラス メンバー、またはその両方を定義することができます。
2) 特定のクラスのオブジェクトは、そのクラスの外部仕様によって、明らかにメンバーオブジェクトにデータを格納する必要がある場合があります。説明のために、一部の節では、クラスの外部仕様を満たすクラスのプライベート メンバー オブジェクトの代表的な宣言とセマンティック要件を提供します。このようなメンバー オブジェクトの宣言と関連するメンバー型の定義の後には、次のように説明のみで終わるコメントが続きます。
streambuf* sb; // exposition only
とはいえ、 に必要な機能についてのいくつかのコメントstd::shared_ptr
:
shared_ptr
は、最後の生きているオブジェクトが明確でなく、この最後のオブジェクトが割り当てを解除する必要があるためです) 。weak_ptr
などweak_ptr::expired
を使用するために、この所有権情報オブジェクトの参照カウントを保存する必要もあります。たとえば、アクセス違反によって失敗するweak_ptr::lock
ことはありません。衒学的な補足: 標準ではメモリをリークしない必要はありませんshared_ptr
が、PC タイプのアーキテクチャの典型的な実装では、おそらく動的メモリ割り当てが使用されます。
std::make_shared
std::shared_ptr
btw は、1 回の割り当てで所有オブジェクトと所有権情報オブジェクトの両方にメモリを割り当てることができるため、ctor of を使用するよりも高速であると見なされます(標準では、「実装は複数のメモリ割り当てを実行しないでください」と述べていますが、それは備考のみ)。