簡體   English   中英

移動語義和重載

[英]Move semantics and overload

我認為我對右值引用和移動語義的理解存在一些漏洞。

就我現在理解的右值引用而言,我可以通過兩種方式實現 function f ,以便它從移動語義中獲益。

第一個版本:同時實現

void f(const T& t);
void f(T&& t);

這將導致相當多的冗余,因為兩個版本可能具有(幾乎)相同的實現。

第二個版本:僅實施

void f(T t);

調用f將導致調用T的復制構造函數或移動構造函數。

問題。 這兩個版本如何相互比較? 我的懷疑:在第二個版本中,移動構造函數可能會移動動態分配的數據(的所有權),而t及其成員中的非動態分配的數據需要復制。 在第一個版本中,兩個版本都沒有分配任何額外的 memory(引用后面的指針除外)。

如果這是正確的,我是否可以避免編寫f的實現基本上兩次而沒有第二個版本的缺點?

如果你需要取一個T&&參數,通常意味着你要把object移到某個地方並保留它。 這種 function 通常與const T&重載配對,因此它可以接受右值和左值。

在這種情況下,第二個版本(只有一個以T作為參數的重載)總是效率較低,但很可能不會差很多。

對於第一個版本,如果您傳遞一個左值,function 會獲取一個引用,然后制作一個副本以將其存儲在某個地方。 那是一個副本構造或分配。 如果你傳遞一個右值,function 再次獲取一個引用,然后移動 object 來存儲它。 那是一步構建或分配。

對於第二個版本,如果你傳遞一個左值,它會被復制到參數中,然后 function 可以移動它。 如果你傳遞一個右值,如果被移動(假設類型有一個移動構造函數)到參數中,然后 function 也可以移動它。 在這兩種情況下,這都比第一個版本多了一個移動構造或分配。

另請注意,在某些情況下可能會發生復制省略

第二個版本的好處是您不需要多次重載。 對於第一個版本,您需要為需要復制或移動的 n 個參數重載 2^n。

在只有一個參數的簡單情況下,我有時會這樣做以避免重復代碼:

void f(const T& t) {
    f_impl(t);
}
void f(T&& t) {
    f_impl(std::move(t));
}

// this function is private or just inaccessible to the user
template<typename U>
void f_impl(U&& t) {
    // use std::forward<U>(t)
}

暫無
暫無

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

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