簡體   English   中英

C ++ Zero of Zero:多態刪除和unique_ptr行為

[英]C++ Rule of Zero : polymorphic deletion and unique_ptr behavior

在最近實施零規則主題下的超載期刊中 ,作者描述了我們如何避免編寫五個操作符規則,因為編寫它們的原因是:

  1. 資源管理
  2. 多態刪除

這兩個都可以通過使用智能指針來處理。

在這里,我對第二部分特別感興趣。

請考慮以下代碼段:

class Base
{
public:
    virtual void Fun() = 0;
};


class Derived : public Base
{
public:

    ~Derived()
    {
        cout << "Derived::~Derived\n";
    }

    void Fun()
    {
        cout << "Derived::Fun\n";
    }
};


int main()
{
    shared_ptr<Base> pB = make_shared<Derived>();
    pB->Fun();
}

在這種情況下,正如文章的作者解釋的那樣,我們通過使用共享指針獲得多態刪除,這確實有效。

但是,如果我用unique_ptr替換shared_ptr ,我將無法再觀察到多態刪除。

現在我的問題是,為什么這兩種行為有所不同? 為什么shared_ptr會處理多態刪除,而unique_ptr卻沒有?

如果您使用C ++ 14 make_unique或在Yakk的答案中編寫自己的一個,它將起作用。 基本上,共享指針行為之間的區別在於:

template<
    class T,
    class Deleter = std::default_delete<T>
> class unique_ptr;

對於unique_pointer並且如您所見,刪除器屬於該類型。 如果聲明unique_pointer<Base>它將始終使用std::default_delete<Base>作為默認值。 make_unique將負責為您的班級使用正確的刪除器。

使用shared_ptr你得到:

template< class Y, class Deleter >
shared_ptr( Y* ptr, Deleter d );

和其他重載作為構造函數。 正如您所看到的, unique_ptr的默認刪除器在聲明類型時取決於模板參數(除非您使用make_unique ),而對於shared_ptr ,刪除器取決於傳遞給構造函數的類型。


你可以看到一個允許沒有虛擬析構函數的情況下進行多態刪除的版本(這個版本也適用於VS2012)。 請注意,它有點被黑客攻擊,我目前還不確定在C ++ 14中unique_ptrmake_shared的行為是什么樣的,但我希望它們能讓這更容易。 也許我會查看有關C ++ 14新增內容的論文,看看如果我以后有空的話會有什么變化。

你有答案: https//stackoverflow.com/a/22861890/2007142

引用:

一旦最后一次引用shared_ptr超出范圍或被重置,將調用~Derived()並釋放內存。 因此,您不需要將~Base()虛擬化。 unique_ptr<Base>make_unique<Derived>不提供此功能,因為它們不提供shared_ptr相對於刪除器的機制,因為唯一指針更簡單並且旨在實現最低開銷,因此不存儲額外的刪除程序所需的函數指針。

template<typename T>
using smart_unique_ptr=std::unique_ptr<T,void(*)(void*)>;

template<class T, class...Args> smart_unique_ptr<T> make_smart_unique(Args&&...args) {
  return {new T(std::forward<Args>(args)...), [](void*t){delete (T*)t;}};
}

問題是unique_ptr的默認刪除器調用存儲指針上的delete 上面存儲了一個知道構造類型的刪除器,因此當復制到基類時, unique_ptr仍將作為子類刪除。

這增加了適度的開銷,因為我們必須取消引用指針。 此外,它smart_unique_ptr類型進行非規范化,因為默認構造的smart_unique_ptr現在是非法的。 您可以通過一些額外的工作來解決這個問題(用至少不會崩潰的半智能仿函數替換原始函數指針:但是,如果在調用刪除器時unique非空,則應該聲明函數指針存在) 。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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