首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Effective Modern C++ 條款 28:理解引用折疊與 std::forward 實作機制

     編輯:關於C++

引用折疊:模板類型推導的核心規則

C++ 禁止直接宣告「引用的引用」 (int& &r),但在模板實例化、auto 推導、typedef/using 別名、decltype 四種語境中,編譯器會產生引用的引用,隨即套用引用折疊規則化為單一引用。

折疊規則表

組合結果口訣
T& &T&有左值引用 → 左值引用
T& &&T&
T&& &T&
T&& &&T&&全右值引用 → 右值引用

萬用引用 (Universal Reference) 的誕生

函數模板參數為 T&& 且 T 為模板參數時,稱為轉發參考 (C++20 正式術語) / 萬用引用。其類型推導編碼實參值類別:

  • 實參為左值 → T 推導為 U& → 參數型別 U& && 折疊為 U& (左值引用)。
  • 實參為右值 → T 推導為 U → 參數型別 U&& (右值引用)。
template
void func(T&& param);  // 轉發參考

Widget w;
func(w);           // 左值 → T=Widget& → param: Widget&
func(Widget{});    // 右值 → T=Widget  → param: Widget&&

std::forward 完美轉發實作原理

std::forward(arg) 只有在原始實參為右值時,將 arg (函數內部為左值) 轉換為右值;左值保持左值。

標準庫實作 (簡化版)

namespace std {
    // C++11
    template
    T&& forward(typename remove_reference::type& arg) noexcept {
        return static_cast(arg);
    }

    // C++14 簡化
    template
    T&& forward(remove_reference_t& arg) noexcept {
        return static_cast(arg);
    }
}

兩種情況逐步推導

情況 1:原始實參為左值

  • 呼叫 func(w),T 推導為 Widget&。
  • forward(param) 實例化:
Widget& forward(Widget& arg) {  // remove_reference::type = Widget
    return static_cast(arg);  // T&& = Widget& && → 折疊為 Widget&
}
  • 結果:static_cast(arg) 無實際轉換,返回左值引用 → 左值。

情況 2:原始實參為右值

  • 呼叫 func(Widget{}),T 推導為 Widget。
  • forward(param) 實例化:
Widget&& forward(Widget& arg) {  // remove_reference::type = Widget
    return static_cast(arg);  // T&& = Widget&&,無折疊
}
  • 結果:static_cast(arg) 將左值 arg 轉為右值引用 → 右值。

四大引用折疊語境

  1. 模板實例化:最常見,如上述 func、forward。
  2. auto 變數推導:auto&& x = expr; 本質同模板推導。
    • auto&& r1 = lvalue; → auto 推導為 T& → T& && 折疊為 T&。
    • auto&& r2 = rvalue; → auto 推導為 T → T&&。
  3. typedef / using 別名:
    template struct Wrapper { using Ref = T&&; };
        Wrapper::Ref  →  int& && → 折疊為 int&  (非右值引用!)
  4. decltype:decltype((expr)) 為左值表達式產生 T&,參與折疊。

核心心法

  1. 引用折疊 讓「引用的引用」在特定語境合法並簡化為單一引用。
  2. 轉發參考 (T&&) 結合「左值推導為 T&、右值推導為 T」與「引用折疊」,實現完美轉發。
  3. std::forward 內部用 static_cast 配合 remove_reference,精準還原實參值類別。
  4. 萬用引用 ≠ 右值引用:它是在滿足類型推導與引用折疊語境下的右值引用語法。
  5. C++14 remove_reference_t、forward 簡化實作,語意不變。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved