簡體   English   中英

為什么不通過右值引用接受 std::unique_ptr?

[英]Why not to accept std::unique_ptr by rvalue reference?

有人可以解釋為什么每個人都按值而不是右值引用傳遞std::unique_ptr嗎?

根據我的觀察,這需要調用一個額外的移動構造函數。

這是一個 class 持有“指針”的例子。 它需要 3 次 move-ctor 調用才能按值獲取它,而需要 2 次調用才能通過引用獲取它:

#include <memory>
#include <iostream>

class pointer {
public:
    pointer()
    { std::cerr << "ctor" << std::endl; }
    
    pointer(const pointer&)
    { std::cerr << "copy-ctor" << std::endl; }
    
    pointer& operator=(const pointer&)
    { std::cerr << "copy-assignment" << std::endl; return *this; }
    
    pointer(pointer&&)
    { std::cerr << "move-ctor" << std::endl; }
    
    pointer& operator=(pointer&&)
    { std::cerr << "move-assignment" << std::endl; return *this; }
    
    ~pointer()
    { std::cerr << "dtor" << std::endl; }
};

class A {
public:
    // V1
    A(pointer _ptr) : ptr(std::move(_ptr)) {}
        
    // V2
    A(pointer&& _ptr) : ptr(std::move(_ptr)) {}

private:
    pointer ptr;
};

int main() {
    // Three calls to move-ctor versus two calls if pass by rvalue reference
    auto ptr = pointer();
    A a(std::move(ptr));

    // Two calls to move-ctor always
    A a(pointer{});
}

通過引用、右值或其他方式傳遞unique_ptr不會實際移動任何東西,因此僅查看 function 聲明您無法知道是否會發生移動。

另一方面,按值傳遞unique_ptr保證傳入的指針將從中移出,因此甚至不必查看文檔,您就知道調用 function 可以使您擺脫指針的所有權。

出於同樣的原因,人們傳遞int而不是const int&

std::unique_ptr只是單個指針值的 RAII 包裝器,因此移動它只是復制單個寄存器寬度值,然后將源清零。 這太微不足道了,避免移動沒有真正的好處。 畢竟,傳遞引用(未內聯時)的成本也是傳遞指針的成本,因此通過引用傳遞可能效率較低(因為如果未內聯,它必須遵循對真實 memory 的引用,然后拉從那里取出值;堆棧的頂部可能在 L1 緩存中,誰知道它存儲的位置是不是?)。

在實踐中,其中大部分將在啟用優化的情況下進行內聯,並且兩種方法都會得到相同的結果。 當按引用傳遞沒有任何好處時,按值傳遞是一個很好的默認設置,那么為什么不這樣做呢?

為什么每個人都按值而不是右值引用傳遞 std::unique_ptr?

它可能更常見,但不是“每個人”。

std::unique_ptr&&參數的缺點是它沒有明確地與調用者溝通指針是否會被移動。 它可能總是移動,或者可能取決於某些條件。 您必須知道實現或至少 API 文檔才能確定。 std::unique_ptr參數的相應好處是它單獨告訴聲明的讀者 function 將獲得指針的所有權。 出於這個原因,使用std::unique_ptr參數可能是一個不錯的選擇,這可能是它更常見的部分原因。

std::unique_ptr&&的好處是避免了額外的移動。 然而,移動std::unique_ptr是一個非常快速的操作。 例如,與 memory 分配本身相比,它是微不足道的。 在大多數情況下,這根本無關緊要。

兩者之間的區別相當微妙。 std::unique_ptr&&參數可能會在您測量到移動成本很高的情況下被考慮。 這不是很常見。 或者在您的 API 可能用於成本可能很高的情況下。 很難證明如果您正在編寫一個 public API 就不會發生這種情況,因此更有可能使用它。

暫無
暫無

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

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