簡體   English   中英

使用std :: unique_ptr有什么好處 <T> 而不是std :: unique_ptr <T> ?

[英]Are there any advantages of using std::unique_ptr<T>& instead of std::unique_ptr<T>?

使用std::unique_ptr<T>&而不是std::unique_ptr<T>有什么好處嗎? 例如,在函數參數中?

有幾種不同的情況

  1. 您想將所有權轉移到該功能
    • 使用std::unique_ptr<T>
  2. 您希望允許該函數修改指針
    • 使用std::unique_ptr<T> &
  3. 您希望允許該函數修改指針
    • 在呼叫站點使用T &和取消引用
    • 如果指針可能為null,則使用T *並在調用站點調用unique_ptr::get
  4. 您希望允許該函數觀察指針
    • 使用const T & ,並在呼叫站點取消引用
    • 如果指針可能為null,則使用const T *並在調用站點調用unique_ptr::get
  5. 您希望允許該函數具有指針的副本
    • 使用T ,並在呼叫站點取消引用
  6. unique_ptr<T>的集合上有一個ranged-for循環(或<algorithm>調用),並且想要觀察值,並且沒有ranges::indirect (或類似
    • 使用auto & ,並且知道它被推斷為std::unique_ptr<T> & (或const std::unique_ptr<T> &如果集合是const ),所以你必須在循環體中取消引用

由於std::unique_ptr無法通過設計進行復制,因此只能通過將指針的所有權傳遞給函數來調用std::unique_ptr<T>的函數(即移動構造)。 調用代碼將無法再訪問指針。

使用std::unique_ptr<T>& ,您允許函數“看到”指針並訪問其成員,但調用代碼保留所有權,因此仍然可以自己使用它。

std :: unique_ptr只能移動,所以如果你按值傳遞unique_ptr,那么你不能在函數調用后提取它的內容,但如果你通過引用傳遞,那么可以檢索值。 以下是相同的示例代碼:

#include <iostream>
#include <memory>
void changeUniquePtrReference(std::unique_ptr<int>& upr)
{
    *upr = 9;   
}
void changeUniquePtrValue(std::unique_ptr<int> upv)
{
    *upv = 10;
}
int main()
{
  std::unique_ptr<int> p(new int);
  *p =8;
  std::cout<<"value of p is "<<*p<<std::endl;
  changeUniquePtrReference(p);
  std::cout<<"value of p is "<<*p<<std::endl;
  changeUniquePtrValue(std::move(p));
  std::cout<<"Memory deallocated so below line will crash.. "<<std::endl;
  std::cout<<"value of p is "<<*p<<std::endl;

  return 0;
}

這兩種變體是不同的,適用於特定情況。

如果您的函數采用std::unique_ptr<T> ,這意味着您對托管對象擁有所有權並將其刪除或將其保存在其他位置。

如果你采用std::unique_ptr<T> & ,你不會獲得所有權,但你可以改變指針指向的內容,例如通過將其重置為不同的對象。

如果您不打算更改指針本身,則只需傳遞T&或const T& ,具體取決於您是否計划修改對象。 傳遞const std::unique_ptr<T> &是沒有用的,因為這不會讓你做更多的事情而不是T& ,具有潛在的額外間接的缺點和對參數的不必要的限制。

Herb Sutter解釋了將智能指針傳遞給具有所有可能變化的函數的所有缺點和優點。 請閱讀文章了解更多信息,它非常好:

簡而言之,將unique_ptr傳遞給沒有引用的函數是沒有意義的,除非你的預期行為是放棄指針的所有權。

就個人而言,我只看到一個你應該傳遞對unique_ptr的引用的情況:那就是你調用的方法可能在內部 決定刪除對象,或者放棄它。 這應該是非常罕見的,因為所有者放棄了對所有權的決定,老實說,這不是很好的設計。

如果子對象總是占用所有權或刪除對象,則參數類型應為unique_ptr 並立即傳遞所有權。

如果子對象只是想訪問指針內容,則參數應該是原始指針。 您可以為const unique_ptr reference創建一個參數,這將阻止您釋放它,但有什么意義呢? 如果你覺得你需要一個超出原始的約定,你可以裝飾那個原始的指針類型名稱,這樣你就知道你不擁有它。

暫無
暫無

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

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