2. キーワードは所有 (ownership)
• “…, so keeping track of an object’s
ownership is hard work.” – More Effective C++
• “Observe the canonical exception-safety
rules: Always use the “RAII” idiom to
resource ownership and management.”
– Exceptional C++
• “Containers of raw pointers make manual
ownership management tricky, so …”
– Modern C++ Design
2 2009/12/14
69. オブジェクト間グローバルマッピング
share_ptr map<void *, Y> g_map; // グローバル
a y1
share_ptr b y2
c y3
share_ptr share_ptr
69 2009/12/14
70. オブジェクト間グローバルマッピング
share_ptr map<void *, Y> g_map; // グローバル
a y1
share_ptr b y2
c y3
c が消えると…
share_ptr share_ptr
70 2009/12/14
71. オブジェクト間グローバルマッピング
share_ptr map<void *, Y> g_map; // グローバル
a y1
share_ptr b y2
c y3
c が消えると… 無駄なマップエントリ
(デッドマップ) が発生
share_ptr share_ptr
71 2009/12/14
72. 策1. キーを weak_ptr にして適度にクリーンアップ
share_ptr map<weak_ptr<void>, Y> g_map;
a y1
share_ptr b y2
c y3
72 2009/12/14
73. 策1. キーを weak_ptr にして適度にクリーンアップ
share_ptr map<weak_ptr<void>, Y> g_map;
a y1
share_ptr b y2
c y3
// 以下を適度に実行
for (auto i = g_map.begin(); i != g_map.end();) {
if (i->first.expired()) g_map.erase(i++);
else ++i;
}
73 2009/12/14
74. 策1. キーを weak_ptr にして適度にクリーンアップ
share_ptr map<weak_ptr<void>, Y> g_map;
a y1
share_ptr b y2
c y3
デッドマップが適度に解消される
74 2009/12/14
76. 策2. マップエントリも所有する
share_ptr map<void *, Y>
a
struct D{ y1
map<void *, Y> &m_;
share_ptr b y2
void operator()(void *p){
m_.erase(p); delete p;
c y3
}
};
D d(g_map);
shared_ptr<C> pc(new C(), D(g_map));
share_ptrg_map.insert(make_pair(pc.get(), Y(…)));
share_ptr
76 2009/12/14
77. 策2. マップエントリも所有する
share_ptr map<void *, Y>
a y1
share_ptr b y2
c y3
c を所有する shared_ptr がなくなると…
share_ptr share_ptr
77 2009/12/14
78. 策2. マップエントリも所有する
share_ptr map<void *, Y>
a y1
share_ptr b y2
c y3
c をキーとするエントリも自動で erase
c を所有する shared_ptr がなくなると…
share_ptr share_ptr
78 2009/12/14
79. 循環所有を何とかする
// こういうことがしたい
shared_ptr<X> px = …;
shared_ptr<Y> py = …;
pyy = px->getSharedY(); // X が Y を所有?
assert(pyy == py);
pxx = py->getSharedX(); // Y が X を所有?
assert(pxx == px);
79 2009/12/14
80. 循環所有を何とかする
// こういうことがしたい
shared_ptr<X> px = …;
shared_ptr<Y> py = …;
所有
pyy = px->getSharedY(); // X が Y を所有?
assert(pyy == py);
X ? Y
pxx = py->getSharedX(); // Y が X を所有?
所有
assert(pxx == px);
80 2009/12/14
81. 循環所有を何とかする
// こういうことがしたい
shared_ptr<X> px = …;
shared_ptr<Y> py = …;
shared_ptr
所有 所有
pyy = px->getSharedY(); // X が Y を所有?
assert(pyy == py);
X Y
pxx = py->getSharedX(); // Y が X を所有?
assert(pxx == px);
81 2009/12/14
82. 循環所有を何とかする
// こういうことがしたい
shared_ptr<X> px = …;
shared_ptr<Y> py = …;
shared_ptr
ポイント
所有 所有
pyy = px->getSharedY(); // X が Y を所有?
assert(pyy == py);
X Y
pxx = py->getSharedX(); // Y が X を所有?
shared_ptr<X>
assert(pxx == px);
82 2009/12/14
83. 循環所有を何とかする
// こういうことがしたい
shared_ptr<X> px = …;
shared_ptr<Y> py = …;
shared_ptr ポイント
所有 所有
pyy = px->getSharedY(); // X が Y を所有?
assert(pyy == py);
X Y
pxx = py->getSharedX(); // Y が X を所有?
shared_ptr<Y>
assert(pxx == px);
83 2009/12/14