Serie: C++
cpp
348 líneas
· Actualizado 2026-04-03
lambda.cpp
C++/Part3_泛型與STL/Ch15_Lambda與函式物件/lambda.cpp
// Ch15 — Lambda 表達式示範
// 編譯:g++ -std=c++17 -Wall -o lambda lambda.cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <string>
#include <iomanip>
// 輔助函式:印出分隔線
void section(const std::string& title) {
std::cout << "\n===== " << title << " =====\n";
}
// 輔助函式:印出 vector 內容
template<typename T>
void printVec(const std::string& label, const std::vector<T>& v) {
std::cout << label;
for (const auto& x : v) std::cout << x << " ";
std::cout << "\n";
}
int main() {
// ========================================================
// 1. Lambda 基本語法
// ========================================================
section("1. Lambda 基本語法");
// 最簡單的 lambda:無參數、無捕獲
auto greet = []() {
std::cout << "你好,這是一個 Lambda!\n";
};
greet();
// 帶參數的 lambda
auto add = [](int a, int b) {
return a + b;
};
std::cout << "3 + 4 = " << add(3, 4) << "\n";
// 明確指定回傳型別
auto safeDivide = [](double a, double b) -> double {
if (b == 0.0) return 0.0;
return a / b;
};
std::cout << "10 / 3 = " << safeDivide(10, 3) << "\n";
std::cout << "10 / 0 = " << safeDivide(10, 0) << "\n";
// 立即呼叫的 lambda(IIFE)
int result = [](int x, int y) { return x * y; }(6, 7);
std::cout << "立即呼叫 lambda:6 * 7 = " << result << "\n";
// ========================================================
// 2. 捕獲 — 以值捕獲(capture by value)
// ========================================================
section("2. 以值捕獲 [=] [x]");
int base = 100;
int bonus = 50;
// [=] 以值捕獲所有外部變數
auto calcTotal1 = [=]() {
return base + bonus;
// base = 200; // 錯誤!以值捕獲的變數是 const
};
std::cout << "[=] base + bonus = " << calcTotal1() << "\n";
// [base] 只捕獲 base
auto calcDouble = [base]() {
return base * 2;
};
std::cout << "[base] base * 2 = " << calcDouble() << "\n";
// 以值捕獲是在 lambda 建立時複製一份
int x = 10;
auto snapshot = [x]() { return x; };
x = 999; // 修改原始值不影響已捕獲的值
std::cout << "原始 x = " << x << ",lambda 中 x = " << snapshot() << "\n";
// ========================================================
// 3. 捕獲 — 以參考捕獲(capture by reference)
// ========================================================
section("3. 以參考捕獲 [&] [&x]");
int counter = 0;
// [&] 以參考捕獲所有外部變數
auto increment = [&]() {
counter++; // 直接修改原始變數
};
increment();
increment();
increment();
std::cout << "[&] counter = " << counter << "(呼叫 3 次 increment)\n";
// [&counter] 只以參考捕獲 counter
auto reset = [&counter]() {
counter = 0;
};
reset();
std::cout << "reset 後 counter = " << counter << "\n";
// ========================================================
// 4. 混合捕獲
// ========================================================
section("4. 混合捕獲 [=, &x] [&, x]");
int total = 0;
int taxRate = 10; // 稅率 10%
// [=, &total]:預設以值捕獲,total 以參考捕獲
auto addWithTax = [=, &total](int price) {
int tax = price * taxRate / 100;
total += price + tax;
// taxRate = 20; // 錯誤!taxRate 是以值捕獲的 const
};
addWithTax(100); // 100 + 10 = 110
addWithTax(200); // 200 + 20 = 220
std::cout << "含稅總價:" << total << "\n";
// [&, taxRate]:預設以參考捕獲,taxRate 以值捕獲
int count2 = 0;
auto countExpensive = [&, taxRate](int price) {
if (price > taxRate * 10) count2++;
// taxRate = 5; // 錯誤!taxRate 是以值捕獲的
};
countExpensive(50);
countExpensive(150);
countExpensive(200);
std::cout << "超過 100 元的商品有 " << count2 << " 個\n";
// ========================================================
// 5. mutable Lambda
// ========================================================
section("5. mutable Lambda");
int seed = 0;
// mutable 允許修改以值捕獲的變數(修改的是副本)
auto idGenerator = [seed]() mutable -> int {
return ++seed;
};
std::cout << "生成 ID:";
for (int i = 0; i < 5; i++) {
std::cout << idGenerator() << " ";
}
std::cout << "\n";
std::cout << "原始 seed 仍為:" << seed << "(不受影響)\n";
// ========================================================
// 6. 泛型 Lambda(auto 參數)
// ========================================================
section("6. 泛型 Lambda(C++14)");
// auto 參數讓 lambda 變成模板
auto print = [](const auto& x) {
std::cout << x << "\n";
};
std::cout << "印出不同型別:\n";
print(42);
print(3.14);
print("C++ Lambda");
print(std::string("std::string 型別"));
// 泛型二元運算
auto multiply = [](auto a, auto b) {
return a * b;
};
std::cout << "int * int:" << multiply(3, 4) << "\n";
std::cout << "double * double:" << multiply(2.5, 4.0) << "\n";
// ========================================================
// 7. Lambda 搭配 sort
// ========================================================
section("7. Lambda + sort");
struct Student {
std::string name;
int score;
};
std::vector<Student> students = {
{"Alice", 88}, {"Bob", 95}, {"Charlie", 72},
{"Diana", 88}, {"Eve", 91}
};
// 按分數降序排列;分數相同按姓名升序
std::sort(students.begin(), students.end(),
[](const Student& a, const Student& b) {
if (a.score != b.score) return a.score > b.score;
return a.name < b.name;
});
std::cout << "排序結果:\n";
for (const auto& s : students) {
std::cout << " " << std::setw(8) << s.name << ":" << s.score << "\n";
}
// ========================================================
// 8. Lambda + find_if / count_if
// ========================================================
section("8. Lambda + find_if / count_if");
std::vector<int> scores = {78, 92, 65, 88, 55, 73, 95, 42, 81, 70};
printVec("全班成績:", scores);
// find_if:找第一個不及格的分數
auto failIt = std::find_if(scores.begin(), scores.end(),
[](int s) { return s < 60; });
if (failIt != scores.end()) {
std::cout << "第一個不及格分數:" << *failIt
<< "(索引 " << (failIt - scores.begin()) << ")\n";
}
// count_if:計算各等級人數
int gradeA = std::count_if(scores.begin(), scores.end(),
[](int s) { return s >= 90; });
int gradeB = std::count_if(scores.begin(), scores.end(),
[](int s) { return s >= 80 && s < 90; });
int gradeC = std::count_if(scores.begin(), scores.end(),
[](int s) { return s >= 70 && s < 80; });
int gradeD = std::count_if(scores.begin(), scores.end(),
[](int s) { return s >= 60 && s < 70; });
int gradeF = std::count_if(scores.begin(), scores.end(),
[](int s) { return s < 60; });
std::cout << "A (90-100):" << gradeA << " 人\n";
std::cout << "B (80-89):" << gradeB << " 人\n";
std::cout << "C (70-79):" << gradeC << " 人\n";
std::cout << "D (60-69):" << gradeD << " 人\n";
std::cout << "F (<60): " << gradeF << " 人\n";
// ========================================================
// 9. Lambda + for_each
// ========================================================
section("9. Lambda + for_each");
std::vector<std::string> fruits = {"蘋果", "香蕉", "櫻桃", "芒果", "葡萄"};
// 帶索引的 for_each
int index = 0;
std::for_each(fruits.begin(), fruits.end(),
[&index](const std::string& fruit) {
std::cout << index + 1 << ". " << fruit << "\n";
index++;
});
// ========================================================
// 10. Lambda + transform
// ========================================================
section("10. Lambda + transform");
std::vector<double> celsius = {0, 20, 37, 100};
std::vector<double> fahrenheit(celsius.size());
// 攝氏轉華氏
std::transform(celsius.begin(), celsius.end(), fahrenheit.begin(),
[](double c) { return c * 9.0 / 5.0 + 32.0; });
std::cout << "溫度轉換:\n";
for (size_t i = 0; i < celsius.size(); i++) {
std::cout << std::fixed << std::setprecision(1)
<< " " << celsius[i] << "°C = "
<< fahrenheit[i] << "°F\n";
}
// ========================================================
// 11. Lambda 回傳 Lambda(高階函式)
// ========================================================
section("11. Lambda 回傳 Lambda");
// 建立一個乘法器工廠
auto makeMultiplier = [](int factor) {
return [factor](int x) { return x * factor; };
};
auto double_it = makeMultiplier(2);
auto triple_it = makeMultiplier(3);
std::cout << "double_it(5) = " << double_it(5) << "\n";
std::cout << "triple_it(5) = " << triple_it(5) << "\n";
// 搭配 transform 使用
std::vector<int> nums = {1, 2, 3, 4, 5};
std::vector<int> tripled(nums.size());
std::transform(nums.begin(), nums.end(), tripled.begin(), triple_it);
printVec("原始:", nums);
printVec("三倍:", tripled);
// ========================================================
// 12. 綜合範例:資料處理管線
// ========================================================
section("12. 綜合範例:資料處理管線");
struct Product {
std::string name;
double price;
int quantity;
};
std::vector<Product> products = {
{"筆記本", 45.0, 100},
{"原子筆", 12.0, 500},
{"橡皮擦", 8.0, 300},
{"尺", 25.0, 200},
{"計算機", 350.0, 50},
{"書包", 890.0, 30}
};
// 篩選:價格 > 20
std::vector<Product> expensive;
std::copy_if(products.begin(), products.end(),
std::back_inserter(expensive),
[](const Product& p) { return p.price > 20.0; });
// 排序:按價格降序
std::sort(expensive.begin(), expensive.end(),
[](const Product& a, const Product& b) {
return a.price > b.price;
});
// 輸出:每個商品的名稱、單價、庫存總價值
std::cout << "價格 > 20 的商品(按價格降序):\n";
std::for_each(expensive.begin(), expensive.end(),
[](const Product& p) {
double totalValue = p.price * p.quantity;
std::cout << " " << std::setw(6) << p.name
<< " 單價:$" << std::setw(7) << std::fixed
<< std::setprecision(1) << p.price
<< " 庫存:" << std::setw(4) << p.quantity
<< " 總值:$" << std::setw(10) << totalValue << "\n";
});
// 計算總庫存價值
double totalInventory = std::accumulate(products.begin(), products.end(), 0.0,
[](double acc, const Product& p) {
return acc + p.price * p.quantity;
});
std::cout << "\n所有商品總庫存價值:$"
<< std::fixed << std::setprecision(1) << totalInventory << "\n";
return 0;
}
Artículos relacionados
C++
c
Actualizado 2026-07-21
deviceAlpha.h
deviceAlpha.h — c source code from the C++ learning materials (C++/Mavis_Homework/FinalProject/deviceAlpha.h).
Leer artículo →
C++
c
Actualizado 2026-07-21
finalproject.c
finalproject.c — c source code from the C++ learning materials (C++/Mavis_Homework/FinalProject/finalproject.c).
Leer artículo →
C++
cpp
Actualizado 2026-07-21
finalproject.cpp
finalproject.cpp — cpp source code from the C++ learning materials (C++/Mavis_Homework/FinalProject/finalproject.cpp).
Leer artículo →
C++
c
Actualizado 2026-07-21
deviceAlpha.h
deviceAlpha.h — c source code from the C++ learning materials (C++/Mavis_Homework/Lab8/deviceAlpha.h).
Leer artículo →
C++
c
Actualizado 2026-07-21
lab8.c
lab8.c — c source code from the C++ learning materials (C++/Mavis_Homework/Lab8/lab8.c).
Leer artículo →
C++
cpp
Actualizado 2026-07-21
lab8.cpp
lab8.cpp — cpp source code from the C++ learning materials (C++/Mavis_Homework/Lab8/lab8.cpp).
Leer artículo →