i007.cc

i007.cc

优先队列-降维打击

05.价值资料

C++高级特性详解

🔷 一、mutable:让值捕获可修改

值捕获默认是 const,加 mutable 后可以修改副本(不影响外部):

cpp
int count = 0;

auto counter = [count]() mutable {
    count++;           // ✅ 修改的是副本
    return count;
};

counter();  // → 1
counter();  // → 2
count;      // → 0,外部完全不受影响!

 

对比引用捕获:

cpp
auto counter2 = [&count]() {
    count++;
};

counter2();  // count → 1
counter2();  // count → 2
count;       // → 2,外部被修改了

 

选择原则:想要”内部计数”但不污染外部 → mutable 值捕获;想同步外部状态 → 引用捕获。


🔷 二、STL 算法中的 Lambda 实战

sort — 自定义排序

cpp
std::vector<std::string> words = {"banana", "apple", "cherry", "fig"};

// 按字符串长度排序
std::sort(words.begin(), words.end(),
    [](const std::string& a, const std::string& b) {
        return a.size() < b.size();
    });
// → fig, apple, banana, cherry

 

find_if — 条件查找

cpp
std::vector<int> v = {3, 7, 2, 9, 4};

int threshold = 6;
auto it = std::find_if(v.begin(), v.end(),
    [threshold](int x) { return x > threshold; }  // 捕获阈值
);

if (it != v.end())
    std::cout << *it;  // → 7(第一个大于6的元素)

 

transform — 批量变换

cpp
std::vector<int> v = {1, 2, 3, 4, 5};
std::vector<int> result(v.size());

std::transform(v.begin(), v.end(), result.begin(),
    [](int x) { return x * x; }
);
// result → {1, 4, 9, 16, 25}

 

for_each + remove_if — 过滤

cpp
std::vector<int> v = {1, 2, 3, 4, 5, 6};

// 删除所有偶数
v.erase(
    std::remove_if(v.begin(), v.end(),
        [](int x) { return x % 2 == 0; }),
    v.end()
);
// v → {1, 3, 5}

 


🔷 三、并发中的 Lambda 配合 std::thread

基本用法

cpp
#include <thread>

std::thread t([]() {
    std::cout << "子线程运行中" << std::endl;
});

t.join();  // 主线程等待子线程结束

 

传参给线程

cpp
auto task = [](int id, std::string msg) {
    std::cout << "线程" << id << ": " << msg << std::endl;
};

std::thread t1(task, 1, "hello");
std::thread t2(task, 2, "world");

t1.join();
t2.join();

 

⚠️ 并发中的引用捕获陷阱

cpp
// ❌ 危险:主线程结束后 data 已销毁
std::vector<int> data = {1, 2, 3};
std::thread t([&data]() {
    // 如果主线程先结束,data 悬空!
    for (auto x : data) std::cout << x;
});
t.detach();  // detach 后主线程不等子线程,极度危险


// ✅ 安全:值捕获,拷贝一份给线程
std::thread t([data]() {  // 拷贝 data
    for (auto x : data) std::cout << x;
});
t.join();  // 或确保 join 在 data 销毁前

 

共享数据用 mutex 保护

cpp
#include <mutex>

int total = 0;
std::mutex mtx;

auto addTask = [&total, &mtx](int val) {
    std::lock_guard<std::mutex> lock(mtx);  // 自动加锁/解锁
    total += val;
};

std::thread t1(addTask, 10);
std::thread t2(addTask, 20);
t1.join();
t2.join();

std::cout << total;  // → 30,安全!

 


🔷 综合对比总结

Lambda 能力图:

定义时绑定环境          调用时接收数据
   [捕获]        +         (传参)          =   完整的"小函数"
     ↓                        ↓
  值捕获(快照)           普通参数
  引用捕获(共享)
  mutable(可改副本)
     ↓
  用于 STL 算法 / 线程 / 回调 / 异步任务

 


下一步可以继续学:

  • std::async / std::future:更高级的异步任务
  • 模板 + Lambda:泛型回调
  • C++20 的 Lambda 新特性(模板Lambda、[=, this] 等)

想继续哪个?

发表回复