C++11 作为 C++ 语言发展的里程碑版本,引入了大量革命性特性,彻底改变了 C++ 程序的编写方式。你在前面的系列中已经掌握了 C++ 基础语法和常规编程技巧,本篇将聚焦 C++11 及后续版本的核心实用特性,通过实战案例讲解并发编程、智能指针深度应用、lambda 表达式高级用法,帮助你编写更高效、更稳定、更易维护的 C++ 程序。
一、并发编程实战:thread 与 mutex
在多核 CPU 时代,并发编程是提升程序性能的核心手段。C++11 首次将并发编程纳入标准库,提供了std::thread、std::mutex等核心组件,告别了依赖平台特定 API(如 pthread)的时代。
1. 基础并发:std::thread 的使用
std::thread封装了线程创建和管理逻辑,让你可以轻松创建多线程程序,无需关注底层系统调用。
实战案例:多线程数据处理
cpp
#include <iostream>
#include <thread>
#include <vector>
#include <numeric>
// 线程执行函数:计算数组指定区间的和
void calculate_sum(const std::vector<int>& data, int start, int end, int& result) {
result = std::accumulate(data.begin() + start, data.begin() + end, 0);
}
int main() {
// 准备测试数据
std::vector<int> data(1000000, 1); // 100万个1
int result1 = 0, result2 = 0;
// 创建两个线程,分别计算前半部分和后半部分的和
std::thread t1(calculate_sum, std::ref(data), 0, 500000, std::ref(result1));
std::thread t2(calculate_sum, std::ref(data), 500000, 1000000, std::ref(result2));
// 等待线程执行完成(必须join,否则程序终止时会崩溃)
t1.join();
t2.join();
// 合并结果
std::cout << "总结果:" << result1 + result2 << std::endl; // 输出1000000
return 0;
}
关键说明:
std::thread构造时传入函数和参数,线程立即启动;std::ref用于传递引用(默认参数是值拷贝),确保线程能修改外部变量;join()等待线程执行完毕,若不调用,线程析构时会调用std::terminate导致程序崩溃;- 可选
detach()让线程后台运行(分离线程),但需注意资源管理,避免主线程提前退出。
2. 线程安全:std::mutex 的应用
多线程共享数据时会出现竞态条件(Race Condition),std::mutex通过互斥锁保证同一时间只有一个线程访问临界区。
实战案例:线程安全的计数器
cpp
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
class SafeCounter {
private:
int count = 0;
std::mutex mtx; // 互斥锁
public:
// 线程安全的自增操作
void increment() {
// std::lock_guard 自动加锁/解锁(RAII),避免手动解锁遗漏
std::lock_guard<std::mutex> lock(mtx);
count++;
}
int get_count() const {
std::lock_guard<std::mutex> lock(mtx);
return count;
}
};
int main() {
SafeCounter counter;
std::vector<std::thread> threads;
// 创建10个线程,每个线程自增1000次
for (int i = 0; i < 10; ++i) {
threads.emplace_back([&counter]() {
for (int j = 0; j < 1000; ++j) {
counter.increment();
}
});
}
// 等待所有线程完成
for (auto& t : threads) {
t.join();
}
// 正确输出10000(无锁会小于10000)
std::cout << "最终计数:" << counter.get_count() << std::endl;
return 0;
}
关键说明:
std::lock_guard遵循 RAII 原则,构造时加锁,析构时解锁,即使临界区抛出异常也能安全解锁;- 避免在临界区执行耗时操作(如 IO、循环),否则会降低并发效率;
- C++14 新增
std::shared_mutex支持读写分离锁(多读单写),适合读多写少的场景。
二、智能指针深度应用:告别内存泄漏
C++11 重构了智能指针体系,std::unique_ptr、std::shared_ptr、std::weak_ptr通过 RAII 机制自动管理内存,从根本上避免内存泄漏和野指针问题。
1. 独占所有权:std::unique_ptr
std::unique_ptr表示独占式所有权,同一时间只有一个指针指向对象,禁止拷贝,支持移动,是性能最优的智能指针。
实战案例:资源独占管理
cpp
#include <iostream>
#include <memory>
#include <fstream>
// 自定义资源(文件句柄)
class FileHandler {
private:
std::ofstream file;
public:
explicit FileHandler(const std::string& filename) : file(filename) {
if (!file.is_open()) {
throw std::runtime_error("文件打开失败");
}
std::cout << "文件已打开:" << filename << std::endl;
}
~FileHandler() {
if (file.is_open()) {
file.close();
std::cout << "文件已关闭" << std::endl;
}
}
void write(const std::string& content) {
file << content << std::endl;
}
// 禁止拷贝(unique_ptr要求资源不可拷贝)
FileHandler(const FileHandler&) = delete;
FileHandler& operator=(const FileHandler&) = delete;
// 允许移动
FileHandler(FileHandler&&) = default;
FileHandler& operator=(FileHandler&&) = default;
};
int main() {
try {
// unique_ptr独占FileHandler资源
std::unique_ptr<FileHandler> fh = std::make_unique<FileHandler>("test.txt");
fh->write("C++11智能指针实战");
// 移动语义:转移所有权
std::unique_ptr<FileHandler> fh2 = std::move(fh);
fh2->write("所有权转移后继续写入");
// fh此时为空,解引用会崩溃
if (!fh) {
std::cout << "fh已失去所有权" << std::endl;
}
} catch (const std::exception& e) {
std::cerr << "错误:" << e.what() << std::endl;
}
// 函数结束时,fh2析构,自动关闭文件
return 0;
}
2. 共享所有权:std::shared_ptr + std::weak_ptr
std::shared_ptr通过引用计数实现共享所有权,std::weak_ptr解决循环引用问题。
三、Lambda 表达式高级用法:简化代码,提升灵活性
Lambda 表达式是 C++11 引入的匿名函数,不仅能简化代码,还能实现复杂的函数式编程逻辑,是现代 C++ 的核心语法糖。
1. 捕获方式进阶
Lambda 的捕获分为值捕获、引用捕获、移动捕获(C++14)、通用捕获(C++14),灵活使用可适配不同场景。
cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
int main() {
int x = 10;
std::string str = "hello";
// 1. 混合捕获:引用捕获x,值捕获str
auto lambda1 = [&x, str]() {
x += 5; // 修改外部x
std::cout << "x=" << x << ", str=" << str << std::endl;
};
lambda1(); // 输出x=15, str=hello
// 2. 移动捕获(C++14):转移所有权
auto lambda2 = [str2 = std::move(str)]() mutable {
str2 += " world";
std::cout << str2 << std::endl; // 输出hello world
};
lambda2();
if (str.empty()) {
std::cout << "str已被移动" << std::endl;
}
// 3. 通用捕获(C++14):捕获并初始化任意变量
auto lambda3 = [y = x + 5]() {
std::cout << "y=" << y << std::endl; // 输出y=20
};
lambda3();
// 4. 结合STL算法:自定义排序规则
std::vector<int> nums = {3, 1, 4, 1, 5, 9};
std::sort(nums.begin(), nums.end(), [](int a, int b) {
return a > b; // 降序排序
});
for (int num : nums) {
std::cout << num << " "; // 输出9 5 4 3 1 1
}
return 0;
}
2. Lambda 作为函数参数 / 返回值
Lambda 可作为 STL 算法的谓词、函数指针替代方案,甚至作为函数返回值(C++14 支持)。
《C++ 小程序编写系列》第八部 内容预告
各位 C++ 开发者,本次 C++11 + 新特性实战的内容到这里就告一段落啦!通过 thread/mutex 实现并发、智能指针管理内存、lambda 表达式简化逻辑的核心技巧,相信大家已经能上手打造更高效、更稳定的 C++ 程序。
而在 《C++ 小程序编写系列(第八部)》中,我们将继续深挖现代 C++ 的进阶实战技巧,聚焦C++11/14/17 后续核心特性 **,带你突破编程瓶颈,实现从 "会用" 到 "活用" 的进阶!后续内容将重点围绕这些方向展开:
✅ STL 容器进阶与高性能使用:解锁 unordered 系列容器优化、emplace 系列接口高效用法,规避 STL 容器的性能陷阱;
✅ 右值引用与移动语义深度实战:彻底搞懂移动构造 / 移动赋值,亲手实现高性能可移动对象,大幅降低程序内存开销;
✅ 类型萃取与模板元编程基础:掌握 C++11 模板新特性,用类型萃取实现编译期类型判断,让模板代码更灵活、更高效;
✅ 异常处理与程序健壮性提升:C++11 异常体系优化,结合实战讲解异常安全设计、自定义异常类,让程序在异常场景下更可控;
✅ 综合实战:高性能数据处理模块:融合前序所有现代 C++ 特性,打造一个支持并发、内存安全、高效解析的工业级数据处理模块,直接落地项目开发。
同时,第八部内容还会加入特性对比与工程选型建议,告诉你不同场景下该如何选择最优的 C++ 新特性组合,让代码不仅符合现代标准,更能适配实际项目的性能、可维护性要求。
敬请期待《C++ 小程序编写系列(第八部)》的更新,让我们继续深耕现代 C++,用更优雅、更高效的代码解决实际开发中的复杂问题!