[英]shared_ptr deletes the object
void ClassName::LocalMethod( )
{
boost::shared_ptr<ClassName> classNamePtr( this );
//some operation with classNamePtr
return;
}
由於classNamePtr在范圍之外,因此當對象從LocalMethod()返回時,該對象將被釋放。 shared_ptr是否足夠聰明,知道ClassName對象仍在作用域中並且不刪除它?
為對象創建一個shared_ptr
是什么意思? 這意味着shared_ptr
所有者現在承擔了對該對象的所有權。 所有權是指對象在需要時將其刪除。 當shared_ptr
的持有者銷毀了它的shared_ptr
,假定該對象沒有其他shared_ptr
,則可能導致該對象被銷毀。
當shared_ptr
是一個類的成員,這意味着該對象的生存期指向的shared_ptr
是至少只要對象,所述shared_ptr
是其成員。 當shared_ptr
在堆棧上時,這意味着shared_ptr
指向的對象的生存期至少與創建該對象的范圍一樣長。一旦該對象脫離堆棧,則可以將其刪除。
唯一應該使用指針並將其包裝到shared_ptr
是在最初 分配對象時。 為什么? 因為對象不知道它是否在shared_ptr
。 不知道 這意味着創建原始shared_ptr
現在有責任將其傳遞給需要共享該內存所有權的其他人。 共享所有權的唯一工作方式是通過shared_ptr
的副本構造函數 。 例如:
shared_ptr<int> p1 = new int(12);
shared_ptr<int> p2 = p1.get();
shared_ptr<int> p3 = p1;
shared_ptr
的副本構造函數在p1
和p3
之間創建共享所有權。 請注意, p2
與p1
不共享所有權 。 他們倆都認為自己擁有相同的內存所有權,但這與共享內存不同。 因為他們倆都認為自己對此擁有獨特的所有權。
因此,當三個指針被破壞時,將發生以下情況。 首先, p3
將被銷毀。 但是由於p3和p1共享該整數的所有權,因此該整數將不會被破壞。 接下來, p2
將被銷毀。 由於它認為它是整數的唯一持有者,因此它將銷毀它。
此時, p1
指向已刪除的內存。 當p1
被銷毀時,它認為它是整數的唯一持有者,因此它將銷毀它。 不好 ,因為它已經被破壞了。
你的問題是這個。 您在一個類的實例中。 並且您需要調用某些函數,這些函數需要一個shared_ptr
。 但是,您所擁有的只是this
,它是一個常規指針。 你是做什么?
您將得到一些建議enable_shared_from_this
示例。 但是考慮一個更相關的問題:“為什么這些函數將shared_ptr
作為參數?”
函數采用的指針類型指示該函數對其參數進行的操作。 如果函數采用shared_ptr
,則意味着它需要擁有該指針。 它需要取得內存的共享所有權。 因此,請查看您的代碼,並詢問這些功能是否確實需要獲取內存所有權。 他們是將shared_ptr
長期存儲在某個地方(即在一個對象中),還是只是在函數調用期間使用它們?
如果是后者,則函數應該使用裸指針,而不是shared_ptr
。 這樣,他們就無法要求所有權。 然后,您的界面將進行自我記錄:指針類型說明所有權。
但是,您可能正在調用確實需要獲取所有權的函數。 然后,您需要使用enable_shared_from_this
。 首先,您的類需要從enable_shared_from_this
派生。 然后,在函數中:
void ClassName::LocalMethod()
{
boost::shared_ptr<ClassName> classNamePtr(shared_from_this());
//some operation with classNamePtr
return;
}
請注意,這里需要付費。 enable_shared_from_this
在類中添加了boost::weak_ptr
。 但是沒有虛擬開銷或類似的開銷。 它不會使類變為虛擬。 enable_shared_from_this
是模板,因此您必須這樣聲明:
class ClassName : public boost::enable_shared_from_this<ClassName>
shared_ptr是否足夠聰明,知道ClassName對象仍在作用域中並且不刪除它?
那不是shared_ptr
工作方式。 當您在構造shared_ptr
時傳遞指針時, shared_ptr
將承擔該指針的所有權 (在本例中為*this
)。 換言之,所述shared_ptr
是假定憑借的事實,即壽命指針對象的總控制shared_ptr
現在擁有它。 因此,擁有該指針的最后一個shared_ptr
會將其刪除。
如果在ClassName::LocalMethod()
之外沒有classNamePtr
副本,則可以在構造classNamePtr
傳遞不執行任何操作的刪除程序。 這是一個自定義刪除器的示例,該刪除器用於防止shared_ptr
刪除其pointee 。 使示例適合您的情況:
struct null_deleter // Does nothing
{
void operator()(void const*) const {}
};
void ClassName::LocalMethod()
{
// Construct a shared_ptr to this, but make it so that it doesn't
// delete the pointee.
boost::shared_ptr<ClassName> classNamePtr(this, null_deleter());
// Some operation with classNamePtr
// The only shared_ptr here will go away as the stack unwinds,
// but because of the null deleter it won't delete this.
return;
}
您還可以使用enable_shared_from_this
從this
獲得shared_ptr
。 請注意,成員函數shared_from_this()
僅在您已經具有指向this
的現有shared_ptr
時才起作用。
class ClassName : public enable_shared_from_this<ClassName>
{
public:
void LocalMethod()
{
boost::shared_ptr<ClassName> classNamePtr = shared_from_this();
}
}
// ...
// This must have been declared somewhere...
shared_ptr<ClassName> p(new ClassName);
// before you call this:
p->LocalMethod();
這是更合適的“官方”方法,與null刪除器方法相比,其功能不那么強大。
也有可能您實際上並不需要首先創建一個shared_ptr
。 在注釋的部分中//some operation with classNamePtr
什么? 可能有比前兩種方法更好的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.