[解決済み] shared_ptr magic :)
質問
Lidström 氏の主張は、構成要素である
shared_ptr<Base> p(new Derived);
は Base が仮想デストラクタを持つ必要はない、ということです。
Armen Tsirunyan : "本当ですか?果たして shared_ptr は正しくクリーンアップされるのでしょうか?この場合、その効果がどのように実装されるかを示していただけませんか?"。
ダニエル・リドストロム : "The shared_ptr はそれ自身のデストラクタを使用してConcreteインスタンスを削除します。これは、C++ コミュニティでは RAII として知られています。私からのアドバイスは、RAIIについてできる限り学ぶことです。あらゆる状況でRAIIを使用することで、C++のコーディングがとても簡単になります。
Armen Tsirunyan : "私はRAIIについて知っていますし、また最終的には shared_ptr への静的ポインタを持つ場合、pn が 0 になったとき、デストラクタは格納された px を削除するかもしれないことは知っています。
Base
への動的なポインタとDerived
でない限りBase
が仮想デストラクタを持っていない限り、これは未定義の動作になります。間違っていたら訂正してください"。Daniel Lidström : "The shared_ptr はスタティック型がConcreteであることを知っています。これは、コンストラクタで渡したので知っているのです! 少しマジックのように見えますが、これはデザインによるもので、非常に素晴らしいものだと断言できます。
では、判定してください。もしそうなら)どのようにして shared_ptr を実装することは、多相クラスに仮想デストラクタを要求することなく、どのように可能でしょうか? よろしくお願いします。
どのように解決するのですか?
はい、shared_ptr をそのように実装することは可能です。Boost はそうしていますし、C++11 標準もこの動作を要求しています。柔軟性の追加として、shared_ptr は単なる参照カウンターを超えるものを管理します。いわゆるdeleterは通常、参照カウンターを含む同じメモリブロックに置かれます。しかし、面白いのは、このdeleterの型はshared_ptrの型の一部ではないことです。これは "type erasure" と呼ばれ、基本的に "polymorphic functions" の実装に使われるのと同じテクニックです。
boost::function
または
std::function
で実際のファンクタの型を隠します。この例を動作させるためには、テンプレート化されたコンストラクタが必要です。
template<class T>
class shared_ptr
{
public:
...
template<class Y>
explicit shared_ptr(Y* p);
...
};
つまり、これをクラスで使用する場合
Base
と
Derived
...
class Base {};
class Derived : public Base {};
int main() {
shared_ptr<Base> sp (new Derived);
}
... テンプレートのコンストラクタに
Y=Derived
を構築するために使用されます。
shared_ptr
オブジェクトを構築するために使用されます。したがって、コンストラクタは適切な削除人オブジェクトと参照カウンタを作成する機会を持ち、この制御ブロックへのポインタをデータメンバとして格納します。参照カウンタがゼロになると、先に作成された
Derived
-を意識したデレタが使用され、オブジェクトが破棄されます。
C++11 標準では、このコンストラクタについて次のように述べています(20.7.2.2.1)。
必要です。
p
は変換可能でなければなりませんT*
.Y
は完全な型でなければならない。 という式はdelete p
は,よく形成されていなければならず,よく定義された振る舞いを有し,例外を投げてはならない。効果。 を構築する。
shared_ptr
オブジェクトを構築する。 その が所有している ポインタp
....
また、デストラクタについては(20.7.2.2)。
効果です。 もし
*this
が 空 または他のshared_ptr
インスタンス (use_count() > 1
) の場合、副作用はありません。 そうでなければ、もし*this
がオブジェクトを所有している場合p
とデレタd
,d(p)
が呼び出されます。 そうでなければ、もし*this
がポインタを所有している場合p
であり、かつdelete p
が呼び出されます。
(太字による強調は私です)。
関連
-
[解決済み】構造体のベクター初期化について
-
[解決済み】C++ クラスヘッダが含まれているときに「不明な型」があるのはなぜですか?重複
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み] error: 'ostream' does not name a type.
-
[解決済み】関数名の前に期待されるイニシャライザー
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】変数やフィールドがvoid宣言されている
-
[解決済み] 変数サイズのオブジェクトが初期化されないことがある c++
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Cygwin Make bash コマンドが見つかりません。
-
[解決済み】C++エラー:の初期化に一致するコンストラクタがありません。
-
[解決済み】「Expected '(' for function-style cast or type construction」エラーの意味とは?
-
[解決済み】「std::operator」で「operator<<」にマッチするものがない。
-
[解決済み】オブジェクト引数のない非静的メンバ関数の呼び出し コンパイラーエラー
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み] gdbを使用してもデバッグシンボルが見つからない
-
[解決済み】'std::cout'への未定義の参照
-
[解決済み] C++で抽象クラスに対して仮想デストラクタを宣言する理由は何ですか?