計數智慧指標要點(shared_ptr)
5.迴圈引用 考慮如下情形: class B; // 並不需要B的完整定義。因為shared_ptr僅擁有指標成員,且不執行delete 之類的操作。 class A { shared_ptr<B> m_pb; }; class B { shared_ptr<A> m_pa; }; shared_ptr<A> pa(new A); shared_ptr<B> pb(new B); pa->m_pb = pb; pb->m_pa = pa; 你會發現,pa和pb由於互相指向對方,引用計數不會歸0導致資源不釋放。 為此引入了一種稱作weak_ptr的東西,本質來講,它並不是智慧指標,若訪問資源需要 由它構造一個shared_ptr,可以認為它是對引用計數的一個計數(weak_count),不是資 源的計數(share_count)。 因此,只要將shared_ptr<A> m_pa;改為weak_ptr<A> m_pa;資源即可正常釋放,而此 時很有可能引用計數物件還存在,只要有weak_ptr指向它;所以使用weak_ptr需要先調 用lock()獲取shared_ptr,若不為空才能訪問資源。 6.典型錯誤 struct A { int a; }; shared_ptr<A> pa(new A); shared_ptr<int> pint(&pa->a); 上面的程式碼顯然是錯誤的; 成員a屬於A物件,生命期由後者控制。 為此shared_ptr提供了一個成為alias ctor的函式,正確用法如下: shared_ptr<int> pint(pa, &pa->a); pint依然與pa共享資源計數,但是,pint包裹的指標不同。這大概也是為什麼 shared_ptr有一個T*,計數物件也有一個T*,貌似重複,其實不然。 再引用書上的例子: int* p = new int(0); shared_ptr<int> sp1(p); shared_ptr<int> sp2(p); 這是錯誤的,p將被釋放兩次; 正確做法是:shared_ptr<int> sp2(sp1); 另外要關注一下enable_shared_from_this的用法,弄懂了weak_ptr應該是很容易寫出實 現的。shared_ptr程式碼量小,功能又很實用,強烈建議不熟悉的自己手寫實現一遍,可 以看boost例子,但是不要去看boost的程式碼實現。實現完成後可以再去做個對比,有什 麼差異、為什麼。