小編這次要給大家分享的是C++11模板參數(shù)的“右值引用”是不是轉(zhuǎn)發(fā)引用,文章內(nèi)容豐富,感興趣的小伙伴可以來了解一下,希望大家閱讀完這篇文章之后能夠有所收獲。
創(chuàng)新互聯(lián)專注于南澗網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠為您提供南澗營銷型網(wǎng)站建設(shè),南澗網(wǎng)站制作、南澗網(wǎng)頁設(shè)計、南澗網(wǎng)站官網(wǎng)定制、微信小程序開發(fā)服務(wù),打造南澗網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供南澗網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。
在C++11中,&&不再只有邏輯與的含義,還可能是右值引用:
void f(int&& i);
但也不盡然,&&還可能是轉(zhuǎn)發(fā)引用:
templatevoid g(T&& obj);
“轉(zhuǎn)發(fā)引用”(forwarding reference)舊稱“通用引用”(universal reference),它的“通用”之處在于你可以拿一個左值綁定給轉(zhuǎn)發(fā)引用,但不能給右值引用:
void f(int&& i) { } templatevoid g(T&& obj) { } int main() { int n = 2; f(1); // f(n); // error g(1); g(n); }
一個函數(shù)的參數(shù)要想成為轉(zhuǎn)發(fā)引用,必須滿足:
換言之,以下函數(shù)的參數(shù)都不是轉(zhuǎn)發(fā)引用:
templatevoid f(const T&&); template void g(typename std::remove_reference &&); template class A { template void h(T&&, const U&); };
另一種情況是auto&&變量也可以成為轉(zhuǎn)發(fā)引用:
auto&& vec = foo();
所以寫范圍for循環(huán)的最好方法是用auto&&:
std::vectorvec; for (auto&& i : vec) { // ... }
有一個例外,當(dāng)auto&&右邊是初始化列表,如auto&& l = {1, 2, 3};時,該變量為std::initializer_list
轉(zhuǎn)發(fā)引用,是用來轉(zhuǎn)發(fā)的。只有當(dāng)你的意圖是轉(zhuǎn)發(fā)參數(shù)時,才寫轉(zhuǎn)發(fā)引用T&&,否則最好把const T&和T&&寫成重載(如果需要的話還可以寫T&,還有不常用的const T&&;其中T是具體類型而非模板參數(shù))。
轉(zhuǎn)發(fā)一個轉(zhuǎn)發(fā)引用需要用std::forward,定義在
調(diào)用g有幾種可能的參數(shù):
你也許會疑惑,為什么std::move不需要
templateconstexpr T&& forward(std::remove_reference_t &) noexcept; template constexpr T&& forward(std::remove_reference_t &&) noexcept;
調(diào)用std::forward時,編譯器無法根據(jù)std::remove_reference_t
但是這并沒有從根本上回答問題,或者可以進(jìn)一步引出新的問題——為什么std::forward的參數(shù)不定義成T&&呢?
原因很簡單,T&&會把T&、const T&、T&&和const T&&(以及對應(yīng)的volatile)都吃掉,有了T&&以后,再寫T&也沒用。
且慢,T&&參數(shù)在傳入函數(shù)是會匹配到T&&嗎?
#include#include void foo(int&) { std::cout << "int&" << std::endl; } void foo(const int&) { std::cout << "const int&" << std::endl; } void foo(int&&) { std::cout << "int&&" << std::endl; } void bar(int&& i) { foo(i); } int main() { int i; bar(std::move(i)); }
不會!程序輸出int&。在函數(shù)bar中,i是一個左值,其類型為int的右值引用。更直接一點(diǎn),它有名字,所以它是左值。
因此,如果std::forward沒有手動指定的模板參數(shù),它將不能區(qū)分T&和T&&——那將是“糟糕轉(zhuǎn)發(fā)”,而不是“完美轉(zhuǎn)發(fā)”了。
最后分析一下std::forward的實(shí)現(xiàn),以下代碼來自libstdc++:
templateconstexpr _Tp&& forward(typename std::remove_reference<_Tp>::type& __t) noexcept { return static_cast<_Tp&&>(__t); } template constexpr _Tp&& forward(typename std::remove_reference<_Tp>::type&& __t) noexcept { static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument" " substituting _Tp is an lvalue reference type"); return static_cast<_Tp&&>(__t); }
綜上,std::forward能完美轉(zhuǎn)發(fā)。
看完這篇關(guān)于C++11模板參數(shù)的“右值引用”是不是轉(zhuǎn)發(fā)引用的文章,如果覺得文章內(nèi)容寫得不錯的話,可以把它分享出去給更多人看到。