真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

C++11模板參數(shù)的“右值引用”是不是轉(zhuǎn)發(fā)引用

小編這次要給大家分享的是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ā)引用:

template
void g(T&& obj);

“轉(zhuǎn)發(fā)引用”(forwarding reference)舊稱“通用引用”(universal reference),它的“通用”之處在于你可以拿一個左值綁定給轉(zhuǎn)發(fā)引用,但不能給右值引用:

void f(int&& i) { }

template
void g(T&& obj) { }

int main()
{
  int n = 2;
  f(1);
// f(n); // error
  g(1);
  g(n);
}

一個函數(shù)的參數(shù)要想成為轉(zhuǎn)發(fā)引用,必須滿足:

  • 參數(shù)類型為T&&,沒有const或volatile;
  • T必須是該函數(shù)的模板參數(shù)。

換言之,以下函數(shù)的參數(shù)都不是轉(zhuǎn)發(fā)引用:

template
void 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::vector vec;
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ù):

  • int i = 1; g(i);,T為int&,調(diào)用g(int&);
  • const int j = 2; g(j);,T為const int&,調(diào)用g(const int&);
  • int k = 3; g(std::move(k));或g(4);,T為int(不是int&&哦?。?,調(diào)用g(int&&)。

你也許會疑惑,為什么std::move不需要而std::forward需要呢?這得從std::forward的簽名說起:

template
constexpr 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反推出T,從而實(shí)例化函數(shù)模板,因此需要手動指明。

但是這并沒有從根本上回答問題,或者可以進(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++:

template
 constexpr _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);
 }
  • 當(dāng)轉(zhuǎn)發(fā)引用T&& obj綁定左值int&時,匹配第一個重載,_Tp即T為int&,返回類型_Tp&&為int&(引用折疊:& &、& &&、&& &都折疊為&,只有&& &&折疊為&&);
  • const int&同理;
  • 當(dāng)轉(zhuǎn)發(fā)引用綁定右值int&&時,匹配第二個重載,_Tp為int,返回類型為int&&;
  • const int&&同理。

綜上,std::forward能完美轉(zhuǎn)發(fā)。

看完這篇關(guān)于C++11模板參數(shù)的“右值引用”是不是轉(zhuǎn)發(fā)引用的文章,如果覺得文章內(nèi)容寫得不錯的話,可以把它分享出去給更多人看到。


本文名稱:C++11模板參數(shù)的“右值引用”是不是轉(zhuǎn)發(fā)引用
當(dāng)前地址:http://weahome.cn/article/jhhegj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部