C++スマートポインタ:weak_ptr実装の詳細
38534 ワード
文書ディレクトリ weak_ptr記述 声明 作用 原理実現 関数メンバー を使用まとめ weak_ptr記述
宣言
ヘッダファイル:
boostライブラリの公式説明によるとweak_ptrはshared_ptr管理の弱い参照オブジェクトのテンプレートクラス.
これでshared_ptrがマルチスレッド中に破棄された場合
マルチスレッド環境でshared_ptrは複数のスレッドで共有でき、rが使用される前にpオブジェクトは
以上の問題に基づいて、
lock()メンバーについて簡単に説明すると、lockメンバーが取得したshared_ptr pポインタによる一時オブジェクトの作成(weak_ptr弱引用の体現)、この一時オブジェクトは同様にpを指し、pがresetのようなdelete引用の操作を執っていても、弱引用オブジェクトはrポインタのライフサイクルが終わるまで改スマートポインタのアドレスを持っている.C++言語設計者の脳の穴に感心せざるを得ない.C++のメモリ操作の自由を保つためには、どんなに精力を費やしてもこの目標を達成して、職人の精神はやっと今日のC++をますます下層のプログラマーに好きになりました.
原理実装
ソースファイル を初期化するようにする. を返します. しか取得できない.
関数メンバーの使用コンストラクタ である. を出力する. として出力. のように出力される.
まとめ
shared_ptrとweak_ptrの主な違いは以下の通りである. shared_ptrオブジェクトは、実際に1つのアドレスコンテンツを指すweak_を初期化することができるptrオブジェクトは、shared_によってオブジェクトを初期化する必要がある特定のアドレスを直接初期化することはできません.ptrデ初期化 weak_ptrはshared_に影響しませんptrの参照カウントは、弱い参照であり、一時的な参照がshared_を指すためです.ptr.shared_を使用ptrオブジェクト初期化weak_ptrはshared_をもたらさないptr参照カウントが増加します.このプロパティによってshared_を解決できます.ptrのループリファレンス問題. weak_ptrは*と取得ポインタ->演算子を解参照していません.lockメンバー関数でのみ対応するshared_を取得できます.ptrインテリジェントポインタオブジェクトは、対応するアドレスとコンテンツを取得します.
参照ドキュメント:http://www.cplusplus.com/reference/memory/weak_ptr/https://www.boost.org/doc/libs/1_66_0/libs/smart_ptr/doc/html/smart_ptr.html#weak_ptr
宣言
ヘッダファイル:
テンプレートクラス:template class weak_ptr
宣言方式:std::weak_ptr statement
さぎょうboostライブラリの公式説明によるとweak_ptrはshared_ptr管理の弱い参照オブジェクトのテンプレートクラス.
weak_ptr
のオブジェクトは、shared_ptr
ポインタのコンストラクション関数を使用してshared_に変換できます.ptrオブジェクト.しかし、ここでshared_ptr
の構造関数パラメータは、weak_であるweak_ptr
のlockメンバーを含む必要がある.ptrはshared_を取得するために使用されるptrのポインタ.これでshared_ptrがマルチスレッド中に破棄された場合
shared_ptr::reset
,weak_ptrのlockメンバーはshared_を保持できます.ptrのメンバーは、現在のshared_までptrは正常に終了します.そうしないと、非常に危険なメモリ漏れが発生します.lock()メンバーの役割については、次のコードで説明します.shared_ptr<int> p(new int(5));
weak_ptr<int> q(p);
// some time later
if(int * r = q.get())
{
// use *r
}
マルチスレッド環境でshared_ptrは複数のスレッドで共有でき、rが使用される前にpオブジェクトは
p.reset()
を実行し、前の記事でshared_ptrの説明(C++スマートポインタ:shared_ptr実装の詳細)では、resetメンバーが現在のshared_をリセットします.ptrポインタの指向.この場合、現在のスレッドがrポインタを使用し続けると、空のアドレスにアクセスする異常な問題が発生するに違いない.以上の問題に基づいて、
weak_ptr::lock()
メンバーを使用してこの問題を解決するshared_ptr<int> p(new int(5));
weak_ptr<int> q(p);
// some time later
// weak_ptr lock shared_ptr
if(shared_ptr<int> r = q.lock())
{
// use *r
}
lock()メンバーについて簡単に説明すると、lockメンバーが取得したshared_ptr pポインタによる一時オブジェクトの作成(weak_ptr弱引用の体現)、この一時オブジェクトは同様にpを指し、pがresetのようなdelete引用の操作を執っていても、弱引用オブジェクトはrポインタのライフサイクルが終わるまで改スマートポインタのアドレスを持っている.C++言語設計者の脳の穴に感心せざるを得ない.C++のメモリ操作の自由を保つためには、どんなに精力を費やしてもこの目標を達成して、職人の精神はやっと今日のC++をますます下層のプログラマーに好きになりました.
原理実装
ソースファイル
/boost/smart_ptr/weak_ptr.hpp
template<class T> class weak_ptr
{
private:
// Borland 5.5.1 specific workarounds
typedef weak_ptr<T> this_type;
constructor
構造関数//
weak_ptr() BOOST_NOEXCEPT : px(0), pn() // never throws in 1.30+
{
}
//
weak_ptr( weak_ptr const & r ) BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
{
}
destructor
構造関数、ここでweak_ptrはデフォルトの解析関数を使用し、一般的にexpired
を使用して空のオブジェクトまたはuser_を返します.count()が0の場合は補助shared_ptr解放参照operator=
1.
weak_ptr & operator=( weak_ptr && r ) BOOST_NOEXCEPT
{
this_type( static_cast< weak_ptr && >( r ) ).swap( *this );
return *this;
}
//2. , lock Y
template<class Y>
weak_ptr & operator=( weak_ptr<Y> const & r ) BOOST_NOEXCEPT
{
boost::detail::sp_assert_convertible< Y, T >();
px = r.lock().get();
pn = r.pn;
return *this;
}
3.
template<class Y>
weak_ptr & operator=( shared_ptr<Y> const & r ) BOOST_NOEXCEPT
{
boost::detail::sp_assert_convertible< Y, T >();
px = r.px;
pn = r.pn;
return *this;
}
weak_ptr::swap
メンバー、2つのweakを交換ptrが指す内容及びアドレス void swap(this_type & other) BOOST_NOEXCEPT
{
// ,
std::swap(px, other.px);
pn.swap(other.pn);
}
weak_ptr::reset
メンバー、・オブジェクトのアドレスと内容を再指定することは、デフォルトのコンストラクタを再使用してvoid reset() BOOST_NOEXCEPT // never throws in 1.30+
{
// swap
this_type().swap(*this);
}
weak_ptr::use_count
メンバー、shared_を取得ptrオブジェクトが参照される回数.空の場合は0 long use_count() const BOOST_NOEXCEPT
{
return pn.use_count();
}
weak_ptr::expired
メンバー、use_によるとcount==0でboolを返し、trueに戻るとlockでweak_を取得します.ptrのポインタは空のポインタ bool expired() const BOOST_NOEXCEPT
{
return pn.use_count() == 0;
}
weak_ptr::lock
メンバー、weak_ptrオブジェクトはshared_を返します.ptr.私たちが前にweakでptrの役割で説明されている、マルチスレッドアクセス防止時のshared_ptrメモリ漏れ.この時点でweak_ptrオブジェクトが取得したポインタは一時ポインタでshared_を指しますptrオブジェクトの前に指すアドレス.shared_ptr<T> lock() const BOOST_NOEXCEPT
{
return shared_ptr<T>( *this, boost::detail::sp_nothrow_tag() );
}
関数メンバーの使用
#include
#include
struct C {int* data;};
int main () {
std::shared_ptr<int> sp (new int);
std::weak_ptr<int> wp1;
std::weak_ptr<int> wp2 (wp1);
std::weak_ptr<int> wp3 (sp);
std::cout << "use_count:
";
//weak_ptr shared_ptr ,
// , wp1 wp2 0
// wp3 shared_ptr , 1
std::cout << "wp1: " << wp1.use_count() << '
';
std::cout << "wp2: " << wp2.use_count() << '
';
std::cout << "wp3: " << wp3.use_count() << '
';
return 0;
}
の出力は、use_count:
wp1: 0
wp2: 0
wp3: 1
weak_ptr::operator=
賦値演算子// weak_ptr::operator= example
#include
#include
int main () {
std::shared_ptr<int> sp1,sp2;
std::weak_ptr<int> wp;
// sharing group:
// --------------
sp1 = std::make_shared<int> (10); // sp1
wp = sp1; // sp1, wp
sp2 = wp.lock(); // sp1, wp, sp2
sp1.reset(); // wp, sp2
// lock , shared_ptr
sp1 = wp.lock(); // sp1, wp, sp2
std::cout << "*sp1: " << *sp1 << '
';
std::cout << "*sp2: " << *sp2 << '
';
return 0;
}
は、以下の*sp1: 10
*sp2: 10
std::weak_ptr::swap
交換ポインタアドレスおよび対応するコンテンツ#include
#include
int main () {
std::shared_ptr<int> sp1 (new int(10));
std::shared_ptr<int> sp2 (new int(20));
std::weak_ptr<int> wp1(sp1);
std::weak_ptr<int> wp2(sp2);
std::cout << "wp1 -> " << *wp1.lock() << " " << wp1.lock() << '
';
std::cout << "wp2 -> " << *wp2.lock() << " " << wp2.lock() << '
';
// swap wp2
//
// , , weak_ptr , share_ptr
wp1.swap(wp2);
std::cout << "sp1 -> " << *sp1 << " " << sp1 << '
';
std::cout << "sp2 -> " << *sp2 << " " << sp2 << '
';
std::cout << "wp1 -> " << *wp1.lock() << " " << wp1.lock() << '
';
std::cout << "wp2 -> " << *wp2.lock() << " " << wp2.lock() << '
';
return 0;
}
は、wp1 -> 10 0x11daf90
wp2 -> 20 0x11dafd0
sp1 -> 10 0x11daf90
sp2 -> 20 0x11dafd0
wp1 -> 20 0x11dafd0
wp2 -> 10 0x11daf90
std::weak_ptr::reset
メンバー、実行後weak_ptrオブジェクトは、デフォルトのコンストラクション関数を再実行するように、空のオブジェクト// weak_ptr::reset example
#include
#include
int main () {
std::shared_ptr<int> sp (new int(10));
std::weak_ptr<int> wp(sp);
std::cout << "1. wp " << (wp.expired()?"is":"is not") << " expired
";
std::cout << "4. wp " << wp.use_count() << " *wp " << *wp.lock() << '
';
wp.reset();
std::cout << "2. wp " << (wp.expired()?"is":"is not") << " expired
";
std::cout << "3. sp " << sp.use_count() << " *sp " << *sp << '
';
return 0;
}
になって、次の1. wp is not expired
2. wp 2 *wp 10
3. wp is expired
4. sp 1 *sp 10
まとめ
shared_ptrとweak_ptrの主な違いは以下の通りである.
参照ドキュメント:http://www.cplusplus.com/reference/memory/weak_ptr/https://www.boost.org/doc/libs/1_66_0/libs/smart_ptr/doc/html/smart_ptr.html#weak_ptr