簡體   English   中英

std::unique_ptr 包括刪除器作為類型的一部分有什么好處

[英]What is the benefit of std::unique_ptr including the deleter as part of the type

為什么std::unique_ptr包含刪除器函數簽名作為模板定義的一部分背后是否有原因?

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

對比

template< class T > class shared_ptr;

unique_ptr的一般目標是在唯一指針超出范圍時自動刪除指針。 當使用默認刪除器(只調用delete )時,除了指針本身之外, unique_ptr對象中不需要任何額外的數據成員。 這意味着默認情況下, unique_ptr幾乎沒有任何開銷(因為它的大部分(如果不是全部)函數都將被內聯)。

但他們也希望能夠提供更改刪除程序的選項,以用於有意義的特殊情況。 提供該選項,同時仍然能夠對其進行優化(存儲和內聯調用)的唯一方法是使其成為類型本身的靜態部分,即通過模板參數。 關鍵是unique_ptr旨在成為原始指針的最小開銷替代方案。

shared_ptr的情況下,目標完全不同,現有的開銷也是如此。 共享指針實際上使用共享存儲(動態分配),在其中存儲指針、引用計數和刪除器對象。 換句話說,已經有很大的開銷和一個合適的地方來放置刪除器對象,而不會導致額外的每個指針開銷。 此外,對於所有引用計數機制,與現有開銷相比,虛擬調用(執行刪除)的開銷相形見絀。 這就是為什么在共享指針中包含類型擦除刪除器對象的便捷功能是很自然的選擇。

而且,如果要創建具有類型擦除刪除器的唯一指針類型,使用模板別名非常簡單:

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

或者類似的東西,比如這個刪除器:

template <typename T>
struct type_erased_delete {
  std::function< void(T*) > f;

  type_erased_delete() : f(std::default_delete<T>()) { };

  template <typename Func>
  type_erased_delete(Func&& aF) : f(std::forward<Func>(aF)) { };

  void operator()(T* p) const { f(p); };
};

template <typename T>
using any_unique_ptr = std::unique_ptr< T, type_erased_delete<T> >;

這意味着,如果刪除器沒有狀態,則unique_ptr不能大於普通指針; 並移動它並不比復制和清零指針更昂貴。

為了能夠處理多種類型的刪除器,就像shared_ptr ,它需要使用類型擦除 為此,每個unique_ptr都需要包含一個指向刪除器的指針(以多態方式調用它),以及一個指向托管對象的指針,使其大小加倍。

shared_ptr已經有額外的開銷,因為它需要一個指針來訪問引用計數。 刪除器可以與引用計數一起存儲。

shared_ptr的情況下,它在刪除器上使用類型擦除。 執行該類型擦除有一些額外的開銷,這是unique_ptr不想要的。 特別是,大多數解決方案都需要為任何函數對象刪除器分配動態內存。 鑒於unique_ptr的目標,我可以理解為什么他們選擇不使用該技術。

另一方面, shared_ptr已經包含了一些額外的引用計數開銷,因為它已經需要動態分配引用計數。 這意味着類型擦除的額外開銷較小。 這就是boost::shared_ptr編寫方式,標准化版本基本上是對它的捕獲。

可以用new[]構造 - 因此需要調用delete[] - 而不是delete

該模板為您提供了此選項以及日志記錄等。

暫無
暫無

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

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