2017-08-24 95 views
3

做正確的事情有了std::forward是有條件投,爲什麼不能編譯器會自動做這項工作時,看到該用戶試圖傳遞參數以其他功能來作爲通用參考。爲什麼的std ::前進需要,不能在編譯器默認

意思,爲什麼編譯器將通過編寫std::forward的方式對用戶做正確的事的責任。

以有效的現代C++爲例。

void process(const Widget& lvalArg); // process lvalues 
void process(Widget&& rvalArg); // process rvalues 

template<typename T> // template that passes 
void logAndProcess(T&& param) // param to process 
{ 
    auto now = // get current time 
    std::chrono::system_clock::now(); 
    makeLogEntry("Calling 'process'", now); 
    process(std::forward<T>(param)); 
} 

在上面的代碼示例中,我知道刪除std::forward將選擇過程中不正確的過載,而是做了正確選擇的過載的正確的事情,爲什麼用戶需要寫std::forward,我的意思是不能編譯做明顯的我們和不想做正確事情的用戶,我們可以改爲std::dont_forward

我可能會丟失一些使用情況下可以編譯困惑什麼是正確的,但在其中,param是普遍的參考和過程的兩個過載提供給編譯器的I看不到任何混亂上述情況。

只是爲了解釋這個問題是如何不同的,它不是爲什麼我們需要當前編譯器行爲中的'std :: forward',但爲什麼編譯器默認顯式調用正確的重載函數傳遍了,包括多次使用的檢測和在上次使用時轉換爲右值。

+2

的默認行爲是安全的。假設我想在'logAndProcess'中調用'process'兩次。如果你忽略了'std :: forward','param'將被複制。相反,如果行爲是你想要的行爲,那麼第二次調用'process'將會有一個'param',它可能已經從第一次調用移動到'process'。此外,*通用引用*現在稱爲*轉發引用*。 – Praetorian

+0

@Praetorian,所以如果你使用std :: forward你確定第二次使用是否安全? 我的意思是即使通過使用std :: forward,你也不知道param發生了什麼,不管它是被移動還是複製,因爲你不知道函數是如何被調用的,通過左值或右值。 – user8063157

+0

@ user8063157 - 不會。但是如果rvalues總是被默認移動,那麼你只能使用它們一次,然後它們就消失了。現在你必須明確地標記上一次使用'std :: move'或'std :: forward'來讓它們「繼續前進」。 –

回答

1

爲命名參數,param始終是一個左值。這意味着沒有std::forwardprocess(param);將始終調用左值過載。

在另一方面,你需要告訴編譯器,當你想將它轉換爲明確右值;編譯器無法爲您做出決定。例如

process(param);     // you don't want param to be passed as rvalue and thus might be moved here 
... 
process(std::forward<T>(param)); // it's fine to be moved now 
相關問題