How to: 建立和使用 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傳回。