如何:创建和使用weak_ptr实例
有时,对象必须存储访问基础对象的一种方法shared_ptr而不会导致引用计数将增加。通常情况下,这种情况发生时之间的循环引用shared_ptr实例。
最好的设计是尽可能避免共享的所有权的指针。但是,如果您必须有共享的所有权shared_ptr实例,避免它们之间的循环引用。当循环引用是不可避免的或甚至更可取,由于某种原因时,使用weak_ptr为一个或多个所有者提供弱引用到另一个shared_ptr。通过使用weak_ptr,您可以创建shared_ptr的加入现有集相关的实例,但这仅基础内存资源是否仍然有效。A weak_ptr本身不参与将引用计数,因此,它不能阻止的引用计数到零。但是,您可以使用weak_ptr来试图获得一份新的shared_ptr使用的初始化。如果内存已被删除, bad_weak_ptr ,则引发异常。如果内存仍然有效,新共享的指针增加引用计数,并可保证内存是有效,只要shared_ptr变量可用。
示例
下面的代码示例显示了一个案例, weak_ptr用来确保正确删除具有循环依赖项的对象。该示例检查时,假定已创建后被认为是可选的解决方案。Controller对象表示,计算机过程中的某些方面,它们独立操作。每个控制器都必须能够在任何时候,查询其他控制器的状态,每个包含一个私有vector<weak_ptr<Controller>>为此目的。每个矢量包含循环引用,因此, weak_ptr实例而不是使用shared_ptr。
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class Controller
{
public:
int Num;
wstring Status;
vector<weak_ptr< Controller >> others;
explicit Controller(int i) : Num(i) , Status(L"On")
{
wcout << L"Creating Controller" << Num << endl;
}
~Controller()
{
wcout << L"Destroying Controller" << Num << endl;
}
// Demonstrates how to test whether the
// pointed-to memory still exists or not.
void CheckStatuses() const
{
for_each(others.begin(), others.end(), [] (weak_ptr<Controller> wp)
{
try
{
auto p = wp.lock();
wcout << L"Status of " << p->Num << " = " << p->Status << endl;
}
catch (bad_weak_ptr b)
{
wcout << L"Null object" << endl;
}
});
}
};
void RunTest()
{
vector<shared_ptr< Controller >> v;
v.push_back(shared_ptr< Controller >(new Controller(0)));
v.push_back(shared_ptr< Controller > (new Controller(1)));
v.push_back(shared_ptr< Controller > (new Controller(2)));
v.push_back(shared_ptr< Controller > (new Controller(3)));
v.push_back(shared_ptr< Controller > (new Controller(4)));
// Each controller depends on all others not being deleted.
// Give each controller a pointer to all the others.
for (int i = 0 ; i < v.size(); i++)
{
for_each(v.begin(), v.end(), [v,i] (shared_ptr<Controller> p)
{
if(p->Num != i)
{
v[i]->others.push_back(weak_ptr<Controller>(p));
wcout << L"push_back to v[" << i << "]: " << p->Num << endl;
}
});
}
for_each(v.begin(), v.end(), [](shared_ptr<Controller>& p)
{
wcout << L"use_count = " << p.use_count() << endl;
p->CheckStatuses();
});
}
int main()
{
RunTest();
wcout << L"Press any key" << endl;
char ch;
cin.getline(&ch, 1);
}
作为一个实验,修改矢量others是vector<shared_ptr<Controller>>,然后在输出中,请注意在任何析构函数被调用时TestRun返回。