簡體   English   中英

shared_ptr刪除對象

[英]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的副本構造函數在p1p3之間創建共享所有權。 請注意, p2p1 不共享所有權 他們倆都認為自己擁有相同的內存所有權,但這與共享內存不同。 因為他們倆都認為自己對此擁有獨特的所有權。

因此,當三個指針被破壞時,將發生以下情況。 首先, 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_thisthis獲得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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM