[解決済み] std::shared_ptr<void>はなぜ動くのか?
疑問点
シャットダウン時に任意のクリーンアップを行うために std::shared_ptr を使用するいくつかのコードを見つけました。最初はこのコードがうまくいくはずがないと思ったのですが、次のように試してみました。
#include <memory>
#include <iostream>
#include <vector>
class test {
public:
test() {
std::cout << "Test created" << std::endl;
}
~test() {
std::cout << "Test destroyed" << std::endl;
}
};
int main() {
std::cout << "At begin of main.\ncreating std::vector<std::shared_ptr<void>>"
<< std::endl;
std::vector<std::shared_ptr<void>> v;
{
std::cout << "Creating test" << std::endl;
v.push_back( std::shared_ptr<test>( new test() ) );
std::cout << "Leaving scope" << std::endl;
}
std::cout << "Leaving main" << std::endl;
return 0;
}
このプログラムは、出力を行います。
At begin of main.
creating std::vector<std::shared_ptr<void>>
Creating test
Test created
Leaving scope
Leaving main
Test destroyed
G++で実装されているstd::shared_ptrsの内部と関係があるようです。これらのオブジェクトは内部ポインタをカウンタと一緒にラップしているので
std::shared_ptr<test>
から
std::shared_ptr<void>
は、おそらくデストラクタの呼び出しに支障をきたすことはないでしょう。この仮定は正しいでしょうか?
そしてもちろん、より重要な質問です。これは標準によって動作することが保証されていますか、または std::shared_ptr の内部へのさらなる変更、他の実装は実際にこのコードを壊すかもしれませんか?
どのように解決するのですか?
トリックは
std::shared_ptr
が型消去を行うことです。基本的には、新しい
shared_ptr
が作成されると、内部で
deleter
関数 (これはコンストラクタの引数として与えることができますが、 もし与えられない場合はデフォルトで
delete
). このとき
shared_ptr
が破壊されると、そのストアドファンクションが呼び出され、それが
deleter
.
std::functionで単純化され、すべての参照カウントや他の問題を回避して行われている型消去の簡単なスケッチは、ここで見ることができます。
template <typename T>
void delete_deleter( void * p ) {
delete static_cast<T*>(p);
}
template <typename T>
class my_unique_ptr {
std::function< void (void*) > deleter;
T * p;
template <typename U>
my_unique_ptr( U * p, std::function< void(void*) > deleter = &delete_deleter<U> )
: p(p), deleter(deleter)
{}
~my_unique_ptr() {
deleter( p );
}
};
int main() {
my_unique_ptr<void> p( new double ); // deleter == &delete_deleter<double>
}
// ~my_unique_ptr calls delete_deleter<double>(p)
を指定すると
shared_ptr
が別のものからコピーされる (あるいはデフォルトで構築される) と、デレタが回されます。
shared_ptr<T>
から
shared_ptr<U>
を呼び出した場合、どのデストラクタを呼び出すかという情報も
deleter
.
関連
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み】浮動小数点数の乱数生成
-
[解決済み】Visual Studioのデバッガーエラー。プログラムを開始できません 指定されたファイルが見つかりません
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み] using namespace std;」はなぜバッドプラクティスだと言われるのですか?
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] なぜC++はPythonよりもstdinからの行の読み込みが遅いのですか?
-
[解決済み] なぜテンプレートはヘッダーファイルでしか実装できないのですか?
-
[解決済み] なぜ、オブジェクトそのものではなく、ポインタを使用しなければならないのですか?
-
[解決済み] C++のmake_sharedと通常のshared_ptrの違いについて
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Visual Studio 2015で「非標準の構文; '&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】Visual Studio 2015で「非標準の構文。'&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み] [Solved] Error C1083: Cannot open include file: 'stdafx.h'
-
[解決済み】致命的なエラー LNK1169: ゲームプログラミングで1つ以上の多重定義されたシンボルが発見された
-
[解決済み] クラスにデフォルトコンストラクタが存在しない。
-
[解決済み] 非静的データメンバの無効な使用
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み】C++ - ステートメントがオーバーロードされた関数のアドレスを解決できない。
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み】Eclipse IDEでC++エラー「nullptrはこのスコープで宣言されていません」が発生する件