這是允許終身管理。
直到weak_count
爲零,控制塊才被銷燬。一旦count
達到零,storage
對象就會被銷燬。這意味着您需要在計數達到零時直接調用storage
的析構函數,並且在控制塊的析構函數中調用而不是。
爲了防止控制塊的析構函數調用storage
的析構函數,storage
的實際類型不能爲T
。
如果我們只有強引用計數,那麼T
會很好(並且更簡單)。
實際上,實現比這更復雜一點。請記住,可以通過分配T
和new
,然後從中構建shared_ptr
來構建shared_ptr。因此,實際控制塊看起來更像是:
template<typename T>
struct shared_ptr_control_block {
std::atomic<long> count;
std::atomic<long> weak_count;
T* ptr;
};
,什麼make_shared
分配是:
template<typename T>
struct both {
shared_ptr_control_block cb;
std::aligned_storage_t<sizeof (T), alignof (T)> storage;
};
而且cb.p
設置爲storage
地址。在make_shared
中分配both
結構意味着我們得到一個內存分配,而不是兩個(並且內存分配很昂貴)。
注意:我已經簡化了:shared_ptr析構函數必須知道控制塊是否爲both
的一部分(在這種情況下,內存無法在完成之前釋放),或者不是(在這種情況下,可以更早釋放)。這可能是一個簡單的布爾標誌(在這種情況下控制塊較大),或者通過在指針中使用一些備用位(這不是可移植的 - 但標準庫實現不必是可移植的)。該實現甚至可以是更多複雜,以避免在make_shared
的情況下在所有處存儲指針。
啊,我明白了。所以如果我們只有一個引用計數(強計數),那麼'T'就足夠了,對吧? –
@ZizhengTai,yes –
值得一提的是,make_shared結合了控制塊和對象,以減少所需的內存分配數量。只需構造一個shared_ptr,就可以爲共享對象分配一個分配,併爲控制塊分配一個分配。 –