首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C++ for_each + 函數指針/仿函數遍歷容器:參數類型解析、引用傳遞、Lambda 現代替代方案

     編輯:程式設計疑難解答

代碼場景

void print(int& a) { cout << a; }
vector v = {1,2,3};
for_each(v.begin(), v.end(), print); // print 作為一元操作傳遞

參數 `int& a` 含義深度解析

  1. 一元可調用對象要求:`for_each` 要求第三個參數接受**單個參數** (容器元素類型或可轉換類型)。
  2. 元素類型推導:`vector` 迭代器解引用類型為 `int&` (左值引用)。
  3. 引用參數匹配:`void print(int& a)` 完美綁定 `int&`,**避免拷貝**,且允許在函數內**修改元素值** (如 `a *= 2`)。
  4. 若改為 `int a` (值傳遞):會拷貝元素,**無法修改原容器數據**,大對象有性能開銷。
  5. 若改為 `const int& a`:只讀訪問,安全、通用 (接受臨時對象)、推薦用於只讀操作。

for_each 執行流程

// 簡化版 for_each 實現
template 
UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f) {
    for (; first != last; ++first) {
        f(*first); // 關鍵:解引用迭代器得到元素 (int&),傳遞給 f
    }
    return f;
}

現代 C++ 替代方案 (C++11/14/17/20)

1. Lambda 表達式 (最推薦、就地可讀)

// 只讀
for_each(v.begin(), v.end(), [](const int& x) { cout << x << ' '; });

// 修改元素
for_each(v.begin(), v.end(), [](int& x) { x *= 2; });

// C++20 範圍版
for_each(views::all(v), [](int& x) { x *= 2; });

2. 範圍-based for 循環 (最簡潔、性能相同)

// 只讀
for (const int& x : v) cout << x << ' ';

// 修改
for (int& x : v) x *= 2;

3. 算法 + Lambda 組合 (函數式風格)

// 查找第一個偶數
auto it = find_if(v.begin(), v.end(), [](int x) { return x % 2 == 0; });

// 統計大於 5 的個數
int cnt = count_if(v.begin(), v.end(), [](int x) { return x > 5; });

函數指針 vs 仿函數 vs Lambda 對比

形式定義狀態攜帶內聯優化適用場景
函數指針`void (*f)(int&)`無 (全局/靜態)難 (間接調用)C 接口、簡單回調
仿函數`struct { void operator()(int&) {} }`可攜帶成員變量易 (編譯器可內聯)STL 經典、需狀態算法
Lambda`[捕獲](參數){體}`捕獲列表攜帶上下文極易 (編譯器極積極內聯)現代 C++ 首選、就地邏輯

總結

`for_each(v.begin(), v.end(), print)` 中 `print(int& a)` 的引用參數**精確匹配容器元素左值引用**,實現**零拷貝訪問**並**支持修改元素**。現代 C++ 推薦使用 **Lambda** 或 **範圍-based for**,代碼更緊湊、優化更激進、捕獲上下文更靈活。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved