2012-03-12 54 views
124

我看到這個在這裏的std ::移動和性病的區別: Move Constructor calling base-class Move Constructor什麼::向前

有人能解釋一下:

  1. std::movestd::forward之間的區別,最好用一些代碼的例子嗎?
  2. 如何去想它很容易,當要使用的
+1

也看到這兩個相關的問題:我應該使用std ::移動或std中移動構建函數/賦值運算符::前鋒?](http://stackoverflow.com/q/8860233/500104)和[如何std :: forward work?](http://stackoverflow.com/q/8526598/500104)(以及重複的問題)。 – Xeo 2012-03-12 17:34:44

+0

「如何輕鬆地考慮它,以及何時使用」當你想要*移動*值時使用'移動',當你想使用完美的轉發時使用'前進'。這裏不是火箭科學;) – 2012-03-12 17:47:02

+0

move()執行無條件轉換,其中forward()根據傳遞的參數執行轉換。 – 2016-05-18 12:24:43

回答

115

std::move需要一個對象,並允許您將其視爲臨時(右值)。雖然它不是一個語義要求,但通常接受對右值的引用的函數將使其無效。當您看到std::move時,表示該對象的值不應該在以後使用,但仍可以分配一個新值並繼續使用它。

std::forward有一個用例:將模板函數參數(在函數內部)強制轉換爲調用者用來傳遞它的值類別(左值或右值)。這允許右值參數作爲右值傳遞,左值作爲左值傳遞,稱爲「完美轉發」。

illustrate要:

void overloaded(int const &arg) { std::cout << "by lvalue\n"; } 
void overloaded(int && arg) { std::cout << "by rvalue\n"; } 

template< typename t > 
/* "t &&" with "t" being template param is special, and adjusts "t" to be 
    (for example) "int &" or non-ref "int" so std::forward knows what to do. */ 
void forwarding(t && arg) { 
    std::cout << "via std::forward: "; 
    overloaded(std::forward<t>(arg)); 
    std::cout << "via std::move: "; 
    overloaded(std::move(arg)); // conceptually this would invalidate arg 
    std::cout << "by simple passing: "; 
    overloaded(arg); 
} 

int main() { 
    std::cout << "initial caller passes rvalue:\n"; 
    forwarding(5); 
    std::cout << "initial caller passes lvalue:\n"; 
    int x = 5; 
    forwarding(x); 
} 

如霍華德提到,也有相似之處這兩個函數簡單地轉換爲引用類型。但是,這些特定的用例(其中包括右值引用類型轉換的有效性的99.9%)外,你應該直接使用static_cast,寫的你在做什麼了很好的解釋。

+0

我不確定'std :: forward'的_only_用例是函數參數的完美轉發。我遇到了想要完美轉發其他內容的情況,例如對象成員。 – 2013-12-11 16:53:44

+0

@GeoffRomer參數的成員?你有一個例子嗎? – Potatoswatter 2013-12-11 23:11:51

+0

我張貼的例子作爲一個單獨的問題:http://stackoverflow.com/questions/20616958/stdforward-without-perfect-forwarding – 2013-12-16 23:47:51

19

std::forward用於向前參數正是它被傳遞給函數的方式。就像這裏顯示:

When to use std::forward to forward arguments?

使用std::move提供了一個對象作爲右值,以匹配可能一招構造或接受右值的函數。即使x本身不是一個右值,它也可以用於std::move(x)

51

std::forwardstd::move都不過是表演。

X x; 
std::move(x); 

上述投射型X的左值表達式x到X型(一個x值是精確的)的右值表達。 move還可以接受右值:

std::move(make_X()); 

,並在這種情況下,它是一種身份的功能:採用X型的右值,並返回一個類型X的右值

隨着std::forward可以選擇目的地一定程度:

X x; 
std::forward<Y>(x); 

施放類型X的左值表達式x到類型Y的表達上有Y可以是什麼限制。 Y可以是X的可訪問的基礎,或者是對X的基礎的引用。Y可以是X或對X的引用。不能用forward來拋棄cv限定符,但可以添加cv-預選賽。 Y不能是隻能從X轉換的類型,除非通過可訪問的Base轉換。

如果Y是一個左值引用,則結果將是一個左值表達式。如果Y不是左值引用,結果將是一個右值(xvalue是精確的)表達式。

forward只有當Y不是左值引用時才能取右值參數。也就是說,你不能左值左值。這是出於安全原因,因爲這樣做通常會導致懸掛引用。但是將右值賦給右值是可以的,並且是允許的。

如果您嘗試將Y指定爲不允許的內容,則錯誤將在編譯時捕獲,而不是在運行時捕獲。

+0

如果我完美地使用'std :: forward'將一個對象轉發給函數,那麼在該函數執行後,我可以使用該對象嗎?我知道,在std :: move的情況下,這是一個未定義的行爲。 – iammilind 2017-12-26 11:32:49

+0

關於'move':https://stackoverflow.com/a/7028318/576911對於'forward',如果你在一個左值傳遞,你的API應該如果它收到一個左值反應。通常這意味着該值將不被修改。但是,如果它是非常量左值,那麼您的API可能已經對其進行了修改。如果你傳入一個右值,這通常意味着你的API可能已經從它移出,並且因此將應用https://stackoverflow.com/a/7028318/576911。 – 2017-12-26 15:29:54

相關問題