面試官:知道泛型 Lambda 嗎?講一下和普通 Lambda 的區別是什么?
在 C++ 中,Lambda 表達式和泛型 Lambda 的核心區別在于 參數類型的聲明方式 和 適用場景。
1. 普通 Lambda(C++11 起)
參數類型必須顯式聲明,類似于普通函數。
適用場景:處理已知具體類型的參數。
語法示例:
auto lambda = [](int a, double b) {
return a + b;
};
特點:
- 參數類型固定(如 int 和 double)。
- 只能處理類型嚴格匹配的輸入。
- 無法直接處理未知類型或模板化參數。
普通 Lambda 的局限性:
auto print_int = [](int x) {
std::cout << x << std::endl;
};
print_int(42); // 合法
print_int(3.14); // 隱式轉換(丟失精度,可能產生警告)
print_int("hello"); // 編譯錯誤:類型不匹配
2. 泛型 Lambda(C++14 起)
參數類型用 auto 聲明,支持類型推導,類似于函數模板。
適用場景:處理未知類型或需要通用代碼的場合。
語法示例:
auto generic_lambda = [](auto a, auto b) {
return a + b;
};
特點:
- 參數類型由編譯器推導(相當于模板參數)。
- 可以處理任意類型(只要操作合法,如支持 a + b)。
- 本質上會生成一個 函數對象模板。
泛型 Lambda 的通用性:
auto print_generic = [](auto x) {
std::cout << x << std::endl;
};
print_generic(42); // 合法
print_generic(3.14); // 合法
print_generic("hello"); // 合法
3. 關鍵區別對比
特性 | 普通 Lambda | 泛型 Lambda |
參數類型 | 顯式聲明(如 | 使用 |
內部實現 | 普通函數對象 | 函數對象模板 |
適用場景 | 已知具體類型 | 未知類型或通用操作 |
類型檢查 | 編譯時檢查類型嚴格匹配 | 編譯時檢查操作是否合法 |
C++ 版本支持 | C++11 | C++14 及以上 |
4. 泛型 Lambda 的高級用法
結合 decltype 和返回類型推導:
auto add = [](auto a, auto b) -> decltype(a + b) {
return a + b;
};
auto result1 = add(3, 4); // int 類型
auto result2 = add(3.5, 4.2); // double 類型
auto result3 = add(std::string("hello"), " world"); // std::string 類型
5. 性能與底層實現
普通 Lambda:生成一個普通的函數對象,類似手動定義的類:
class __Lambda_1 {
public:
int operator()(int a, double b) const {
return a + b;
}
};
泛型 Lambda:生成一個模板化的函數對象:
class __Lambda_2 {
public:
template <typename T1, typename T2>
auto operator()(T1 a, T2 b) const {
return a + b;
}
};
6. 何時選擇哪種 Lambda?
普通 Lambda:
- 明確知道參數類型。
- 需要強制類型安全(例如避免隱式轉換)。
泛型 Lambda:
- 需要處理多種類型。
- 編寫通用代碼(如容器操作、數學計算)。
- 結合 decltype 或 if constexpr 實現編譯時分派。
7.總結
普通 Lambda | 泛型 Lambda | |
核心優勢 | 類型安全、簡單直觀 | 靈活通用、代碼簡潔 |
典型用途 | 替代簡單函數、回調函數 | 通用算法、類型無關操作 |
代碼生成 | 生成具體類型的函數對象 | 生成模板化的函數對象 |
適用版本 | C++11 | C++14 及以上 |
泛型 Lambda 是普通 Lambda 的擴展,通過 auto 參數實現了類似模板的泛型能力。