1. 从示例代码看C++进阶之路
刚接触C++时,我们往往被指针、引用、模板这些基础概念困扰。但当你能熟练写出"Hello World"后,真正的挑战才刚刚开始。最近在重构一个历史项目时,我深刻体会到:C++的进阶不在于语法细节的堆砌,而在于对编程范式和设计哲学的把握。下面通过几个典型示例,聊聊如何突破C++的中级水平瓶颈。
2. 资源管理:从RAII到智能指针
2.1 传统资源管理的痛点
先看一个文件操作的原始版本:
cpp复制void processFile() {
FILE* file = fopen("data.txt", "r");
if(!file) return;
char buffer[256];
while(fgets(buffer, sizeof(buffer), file)) {
// 处理数据
}
// 容易忘记的关闭操作
fclose(file);
}
这段代码至少有3个隐患:
- 忘记fclose导致资源泄漏
- 异常安全无保障
- 缓冲区大小硬编码
2.2 现代C++的解决方案
使用RAII包装器改造后:
cpp复制class FileHandle {
public:
explicit FileHandle(const char* path, const char* mode)
: handle(fopen(path, mode)) {}
~FileHandle() { if(handle) fclose(handle); }
// 禁用拷贝
FileHandle(const FileHandle&) = delete;
FileHandle& operator=(const FileHandle&) = delete;
// 启用移动
FileHandle(FileHandle&& other) noexcept
: handle(other.handle) { other.handle = nullptr; }
operator FILE*() { return handle; }
private:
FILE* handle;
};
void processFile() {
FileHandle file("data.txt", "r");
if(!file) return;
std::array<char, 256> buffer;
while(fgets(buffer.data(), buffer.size(), file)) {
// 异常安全的处理逻辑
}
}
关键改进点:
- 资源获取即初始化(RAII)保证自动释放
- 禁用拷贝避免重复释放
- 启用移动支持所有权转移
- 使用std::array替代C风格数组
实际项目中更推荐直接使用std::fstream,这里仅为演示RAII模式
3. 模板元编程实战
3.1 类型萃取的应用场景
考虑一个日志函数:
cpp复制void log(const std::string& message);
当需要记录数值时,传统做法:
cpp复制log("Value: " + std::to_string(42));
通过模板和类型萃取可以优化:
cpp复制template<typename T>
std::string toString(const T& value) {
if constexpr(std::is_arithmetic_v<T>) {
return std::to_string(value);
} else {
return value;
}
}
template<typename... Args>
void log(Args&&... args) {
std::ostringstream stream;
(stream << ... << toString(std::forward<Args>(args)));
output(stream.str());
}
现在可以这样调用:
cpp复制log("Value: ", 42, ", Flag: ", true);
3.2 SFINAE与概念约束
检查类型是否可序列化的经典实现:
cpp复制template<typename T, typename = void>
struct is_serializable : std::false_type {};
template<typename T>
struct is_serializable<T, std::void_t<decltype(std::declval<T>().serialize())>>
: std::true_type {};
template<typename T>
void save(const T& obj) {
static_assert(is_serializable<T>::value, "Type not serializable");
// 序列化逻辑
}
C++20概念更简洁:
cpp复制template<typename T>
concept Serializable = requires(T obj) {
{ obj.serialize() } -> std::convertible_to<std::string>;
};
template<Serializable T>
void save(const T& obj) {
// 编译期已确保类型合规
}
4. 并发编程模式
4.1 线程安全队列实现
标准库的queue不是线程安全的,典型实现方案:
cpp复制template<typename T>
class ConcurrentQueue {
public:
void push(T value) {
std::lock_guard<std::mutex> lock(mutex_);
queue_.push(std::move(value));
cond_.notify_one();
}
bool try_pop(T& value) {
std::lock_guard<std::mutex> lock(mutex_);
if(queue_.empty()) return false;
value = std::move(queue_.front());
queue_.pop();
return true;
}
void wait_and_pop(T& value) {
std::unique_lock<std::mutex> lock(mutex_);
cond_.wait(lock, [this]{ return !queue_.empty(); });
value = std::move(queue_.front());
queue_.pop();
}
private:
std::queue<T> queue_;
std::mutex mutex_;
std::condition_variable cond_;
};
关键设计要点:
- 使用unique_lock配合条件变量
- 提供阻塞和非阻塞两种接口
- 完美转发保持移动语义
4.2 原子操作的内存顺序
对比两种自旋锁实现:
cpp复制// 版本1:简单但不正确
class SpinLock {
std::atomic_flag flag;
public:
void lock() { while(flag.test_and_set()); }
void unlock() { flag.clear(); }
};
// 版本2:正确的内存序
class CorrectSpinLock {
std::atomic_flag flag = ATOMIC_FLAG_INIT;
public:
void lock() {
while(flag.test_and_set(std::memory_order_acquire));
}
void unlock() {
flag.clear(std::memory_order_release);
}
};
内存序的选择直接影响:
- 编译器指令重排
- CPU缓存一致性
- 多核间的可见性顺序
5. 性能优化技巧
5.1 避免虚函数开销
动态多态的替代方案:
cpp复制// 传统虚函数
class Shape {
public:
virtual double area() const = 0;
};
// 使用std::variant的方案
using Shape = std::variant<Circle, Rectangle>;
double area(const Shape& shape) {
return std::visit([](auto&& s){ return s.area(); }, shape);
}
性能对比:
| 方案 | 调用开销 | 内存占用 | 扩展性 |
|---|---|---|---|
| 虚函数 | 间接跳转 | 虚表指针 | 需修改基类 |
| variant | 编译期分发 | 最大类型大小 | 非侵入式 |
5.2 缓存友好设计
矩阵乘法的两种实现:
cpp复制// 低效版本:列优先访问
void multiply(const Matrix& a, const Matrix& b, Matrix& result) {
for(int i=0; i<rows; ++i)
for(int k=0; k<cols; ++k)
for(int j=0; j<cols; ++j)
result[i][j] += a[i][k] * b[k][j];
}
// 高效版本:缓存局部性优化
void multiply_optimized(const Matrix& a, const Matrix& b, Matrix& result) {
for(int i=0; i<rows; ++i)
for(int j=0; j<cols; ++j) {
auto sum = result[i][j];
for(int k=0; k<cols; ++k)
sum += a[i][k] * b[k][j];
result[i][j] = sum;
}
}
优化效果:
- 减少缓存失效次数
- 预取友好访问模式
- 实测可能有5-10倍性能差距
6. 现代C++工程实践
6.1 模块化编译
传统头文件的问题:
cpp复制// widget.h
#pragma once
#include <vector>
#include "helper.h" // 传递依赖
class Widget {
std::vector<Helper> helpers;
};
模块化改造:
cpp复制// widget.ixx
export module Widget;
import std.core;
import Helper;
export class Widget {
std::vector<Helper> helpers;
};
优势对比:
- 隔离编译依赖
- 加快增量编译
- 更清晰的接口定义
6.2 静态分析集成
CMake配置示例:
cmake复制find_program(CLANG_TIDY_EXE NAMES "clang-tidy")
if(CLANG_TIDY_EXE)
set(CMAKE_CXX_CLANG_TIDY
${CLANG_TIDY_EXE}
-checks=modernize-*,clang-analyzer-*
-warnings-as-errors=*)
endif()
推荐的检查项:
- modernize-use-nodiscard
- clang-analyzer-core.NullDereference
- bugprone-use-after-move
- performance-unnecessary-copy-initialization
7. 调试与问题排查
7.1 自定义断言宏
超越assert的增强版本:
cpp复制#define ASSERT(expr) \
((expr) ? (void)0 : []{ \
std::cerr << "Assertion failed: " #expr \
<< "\nFile: " << __FILE__ \
<< "\nLine: " << __LINE__ \
<< "\nFunction: " << __PRETTY_FUNCTION__; \
std::abort(); \
}())
扩展方向:
- 日志系统集成
- 堆栈回溯收集
- 条件触发断点
7.2 内存错误诊断
AddressSanitizer使用示例:
bash复制clang++ -fsanitize=address -g demo.cpp
常见错误检测:
- 堆栈缓冲区溢出
- 使用后释放
- 内存泄漏
- 双重释放
Valgrind替代方案:
bash复制valgrind --leak-check=full ./a.out
8. 设计模式新解
8.1 策略模式现代化
传统实现:
cpp复制class SortStrategy {
public:
virtual void sort(std::vector<int>&) = 0;
};
class QuickSort : public SortStrategy { /*...*/ };
class MergeSort : public SortStrategy { /*...*/ };
C++17改进版:
cpp复制using SortStrategy = std::function<void(std::vector<int>&)>;
SortStrategy quick = [](auto& v) { /*...*/ };
SortStrategy merge = [](auto& v) { /*...*/ };
void process(SortStrategy strategy) {
std::vector<int> data;
strategy(data);
}
优势分析:
- 无继承层次
- 支持lambda捕获
- 接口更灵活
8.2 观察者模式优化
基于信号的实现:
cpp复制template<typename... Args>
class Signal {
std::vector<std::function<void(Args...)>> slots;
public:
void connect(std::function<void(Args...)> f) {
slots.push_back(std::move(f));
}
void emit(Args... args) {
for(auto& slot : slots) slot(args...);
}
};
// 使用示例
Signal<int, std::string> dataChanged;
dataChanged.connect([](int id, std::string name){
std::cout << "Data updated: " << id << " - " << name;
});
9. 跨语言交互实践
9.1 C接口封装要点
安全封装示例:
cpp复制extern "C" {
struct CHandle;
CHandle* create_handle(const char* config);
void process_data(CHandle* handle, double* in, double* out);
void destroy_handle(CHandle* handle);
}
class SafeHandle {
CHandle* raw;
public:
explicit SafeHandle(const std::string& config)
: raw(create_handle(config.c_str())) {}
~SafeHandle() { if(raw) destroy_handle(raw); }
std::vector<double> process(const std::vector<double>& input) {
std::vector<double> output(input.size());
process_data(raw, const_cast<double*>(input.data()), output.data());
return output;
}
// 禁用拷贝
SafeHandle(const SafeHandle&) = delete;
SafeHandle& operator=(const SafeHandle&) = delete;
// 允许移动
SafeHandle(SafeHandle&& other) noexcept : raw(other.raw) {
other.raw = nullptr;
}
};
9.2 Python扩展开发
pybind11示例:
cpp复制#include <pybind11/pybind11.h>
namespace py = pybind11;
class Pet {
public:
Pet(const std::string &name) : name(name) {}
void setName(const std::string &name_) { name = name_; }
const std::string &getName() const { return name; }
private:
std::string name;
};
PYBIND11_MODULE(example, m) {
py::class_<Pet>(m, "Pet")
.def(py::init<const std::string &>())
.def("setName", &Pet::setName)
.def("getName", &Pet::getName);
}
编译后Python调用:
python复制import example
p = Pet("Molly")
print(p.getName())
10. 工具链深度集成
10.1 编译期反射探索
使用预处理器生成元信息:
cpp复制#define REGISTER_CLASS(ClassName, ...) \
template<> \
struct ClassMeta<ClassName> { \
static constexpr auto name = #ClassName; \
static constexpr auto fields = std::make_tuple(__VA_ARGS__); \
};
struct Person {
std::string name;
int age;
};
REGISTER_CLASS(Person,
FIELD(name),
FIELD(age)
);
应用场景:
- 序列化/反序列化
- ORM映射
- 运行时类型检查
10.2 自定义分配器实践
内存池实现框架:
cpp复制template<typename T>
class PoolAllocator {
public:
using value_type = T;
PoolAllocator() = default;
template<typename U>
PoolAllocator(const PoolAllocator<U>&) noexcept {}
T* allocate(size_t n) {
if(n != 1) throw std::bad_alloc();
return static_cast<T*>(pool_.allocate());
}
void deallocate(T* p, size_t n) {
pool_.deallocate(p);
}
private:
static MemoryPool& pool_;
};
// 使用示例
std::vector<int, PoolAllocator<int>> vec;
11. 测试驱动开发
11.1 单元测试框架选择
Google Test与Catch2对比:
| 特性 | Google Test | Catch2 |
|---|---|---|
| 断言风格 | EXPECT/ASSERT宏 | REQUIRE/CHECK表达式 |
| 夹具系统 | TEST_F宏 | SECTION分层 |
| 基准测试 | 需额外库 | 内置支持 |
| 编译速度 | 较慢 | 较快 |
11.2 模拟对象实现
手工模拟示例:
cpp复制class Database {
public:
virtual ~Database() = default;
virtual std::string query(const std::string&) = 0;
};
class MockDB : public Database {
public:
MOCK_METHOD(std::string, query, (const std::string&), (override));
};
TEST(ServiceTest, HandlesQuery) {
MockDB db;
EXPECT_CALL(db, query("test"))
.WillOnce(Return("result"));
Service service(db);
ASSERT_EQ(service.process("test"), "processed: result");
}
12. 持续集成实践
12.1 自动化构建流程
GitLab CI示例:
yaml复制stages:
- build
- test
- deploy
cpp-build:
stage: build
script:
- mkdir build
- cd build
- cmake -DCMAKE_BUILD_TYPE=Release ..
- cmake --build . --parallel 4
unit-test:
stage: test
script:
- cd build
- ctest --output-on-failure
12.2 代码质量门禁
SonarQube配置要点:
properties复制sonar.cxx.file.suffixes=.cpp,.hpp,.cc,.h
sonar.cxx.compiler.reportPath=build/compile_commands.json
sonar.cxx.coverage.reportPath=build/coverage.xml
sonar.cxx.clangsa.reportPath=build/scan-build
13. 性能剖析方法
13.1 采样分析工具
perf基本工作流:
bash复制perf record -g ./application
perf report -n --stdio
关键指标:
- CPU周期分布
- 缓存命中率
- 分支预测失败
13.2 微基准测试
Google Benchmark示例:
cpp复制static void BM_StringCopy(benchmark::State& state) {
std::string x = "hello";
for (auto _ : state)
std::string copy(x);
}
BENCHMARK(BM_StringCopy);
BENCHMARK_MAIN();
输出解读:
- 每次迭代纳秒数
- CPU周期计数
- 指令级并行度
14. 多范式编程融合
14.1 函数式风格应用
C++20 ranges示例:
cpp复制auto results = views::iota(1, 100)
| views::filter([](int x){ return x%2 == 0; })
| views::transform([](int x){ return x*x; })
| views::take(10);
对比传统写法:
- 无中间变量
- 惰性求值
- 管道式组合
14.2 协程实践
生成器实现:
cpp复制Generator<int> fibonacci() {
co_yield 0;
co_yield 1;
int a = 0, b = 1;
while(true) {
co_yield a + b;
b = a + b;
a = b - a;
}
}
使用方式:
cpp复制for(int num : fibonacci() | std::views::take(10)) {
std::cout << num << " ";
}
15. 嵌入式开发特例
15.1 寄存器操作安全封装
MMIO访问模式:
cpp复制template<typename T, uintptr_t Addr>
struct Register {
static void set(T value) {
*reinterpret_cast<volatile T*>(Addr) = value;
}
static T get() {
return *reinterpret_cast<volatile T*>(Addr);
}
static void modify(auto f) {
auto value = get();
f(value);
set(value);
}
};
// 使用示例
Register<uint32_t, 0x40021000>::modify([](auto& r){
r |= (1 << 4);
});
15.2 低延迟设计技巧
关键优化手段:
- 禁用异常和RTTI
- 静态内存分配
- 自定义内存管理
- 中断上下文优化
16. 图形计算优化
16.1 SIMD指令应用
AVX2向量化示例:
cpp复制void addArrays(float* a, float* b, float* c, size_t n) {
for(size_t i=0; i<n; i+=8) {
__m256 va = _mm256_load_ps(a+i);
__m256 vb = _mm256_load_ps(b+i);
__m256 vc = _mm256_add_ps(va, vb);
_mm256_store_ps(c+i, vc);
}
}
性能提升要点:
- 数据对齐保证
- 循环展开策略
- 避免混用SSE/AVX
16.2 GPU计算接口
OpenCL内核示例:
cpp复制__kernel void vectorAdd(
__global const float* a,
__global const float* b,
__global float* c)
{
int gid = get_global_id(0);
c[gid] = a[gid] + b[gid];
}
主机端调用流程:
- 选择计算设备
- 创建上下文和命令队列
- 编译内核程序
- 设置参数并执行
- 读取结果
17. 安全编程要点
17.1 密码学API使用
OpenSSL AES加密示例:
cpp复制std::vector<unsigned char> encryptAES(
const std::string& plaintext,
const std::array<unsigned char, 32>& key,
const std::array<unsigned char, 16>& iv)
{
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key.data(), iv.data());
std::vector<unsigned char> ciphertext(plaintext.size() + EVP_MAX_BLOCK_LENGTH);
int len;
EVP_EncryptUpdate(ctx, ciphertext.data(), &len,
reinterpret_cast<const unsigned char*>(plaintext.data()), plaintext.size());
int final_len;
EVP_EncryptFinal_ex(ctx, ciphertext.data() + len, &final_len);
EVP_CIPHER_CTX_free(ctx);
ciphertext.resize(len + final_len);
return ciphertext;
}
17.2 安全编码规范
关键准则:
- 所有数组访问必须边界检查
- 禁用不安全的C函数(strcpy等)
- 敏感数据及时清零
- 最小权限原则
18. 调试技巧进阶
18.1 核心转储分析
gdb调试步骤:
bash复制gdb ./executable core
bt full # 查看完整堆栈
info locals # 检查局部变量
x/20xw $sp # 检查栈内存
18.2 条件断点设置
高级断点示例:
gdb复制# 内存写入断点
watch *(int*)0x7fffffffe3a4
# 条件断点
break foo.cpp:42 if x > 100
# 命令自动化
define printvars
print var1
print var2
end
19. 代码生成技术
19.1 模板元编程进阶
编译期字符串处理:
cpp复制template<size_t N>
struct FixedString {
char buf[N+1] = {};
constexpr FixedString(const char (&s)[N]) {
std::copy_n(s, N, buf);
}
};
template<FixedString S>
struct DebugInfo {
static constexpr auto value = S;
};
// 使用示例
DebugInfo<"config">::value.buf; // 编译期字符串
19.2 LLVM IR生成
简单函数生成示例:
cpp复制llvm::Function* createAddFunc(llvm::Module* module) {
auto& context = module->getContext();
auto* funcType = llvm::FunctionType::get(
llvm::Type::getInt32Ty(context),
{llvm::Type::getInt32Ty(context), llvm::Type::getInt32Ty(context)},
false);
auto* func = llvm::Function::Create(
funcType, llvm::Function::ExternalLinkage, "add", module);
auto* entry = llvm::BasicBlock::Create(context, "entry", func);
llvm::IRBuilder<> builder(entry);
auto* sum = builder.CreateAdd(
func->getArg(0), func->getArg(1), "sum");
builder.CreateRet(sum);
return func;
}
20. 领域特定设计
20.1 游戏开发模式
ECS架构核心:
cpp复制struct Position { float x, y; };
struct Velocity { float dx, dy; };
void movementSystem(entt::registry& registry) {
auto view = registry.view<Position, Velocity>();
view.each([](auto& pos, auto& vel) {
pos.x += vel.dx;
pos.y += vel.dy;
});
}
20.2 金融计算优化
定点数实现示例:
cpp复制template<int Precision>
class FixedPoint {
int64_t value;
public:
FixedPoint(double d) : value(d * (1LL << Precision)) {}
FixedPoint operator+(FixedPoint other) const {
return fromRaw(value + other.value);
}
double toDouble() const {
return static_cast<double>(value) / (1LL << Precision);
}
private:
static FixedPoint fromRaw(int64_t raw) {
FixedPoint result;
result.value = raw;
return result;
}
};
21. 编译期计算实践
21.1 常量表达式进阶
C++20 consteval示例:
cpp复制consteval int factorial(int n) {
if(n <= 1) return 1;
return n * factorial(n-1);
}
static_assert(factorial(5) == 120);
21.2 类型列表操作
模板元函数示例:
cpp复制template<typename... Ts>
struct TypeList;
template<typename List>
struct Length;
template<typename... Ts>
struct Length<TypeList<Ts...>> {
static constexpr size_t value = sizeof...(Ts);
};
// 使用示例
static_assert(Length<TypeList<int, float, char>>::value == 3);
22. 标准库深度使用
22.1 自定义分配器
内存池分配器示例:
cpp复制template<typename T>
class PoolAllocator {
public:
using value_type = T;
PoolAllocator() = default;
template<typename U>
PoolAllocator(const PoolAllocator<U>&) noexcept {}
T* allocate(size_t n) {
return static_cast<T*>(pool_.allocate(n * sizeof(T)));
}
void deallocate(T* p, size_t n) {
pool_.deallocate(p, n * sizeof(T));
}
private:
static MemoryPool& pool_;
};
22.2 并行算法应用
执行策略选择:
cpp复制std::vector<int> data(1000000);
// 顺序执行
std::sort(data.begin(), data.end());
// 并行执行
std::sort(std::execution::par, data.begin(), data.end());
// 向量化并行
std::transform(std::execution::par_unseq,
data.begin(), data.end(), data.begin(),
[](int x){ return x * 2; });
23. 异常安全保证
23.1 基本异常安全
资源管理示例:
cpp复制class DatabaseConnection {
Handle* handle;
public:
DatabaseConnection() : handle(createHandle()) {
try {
initialize(handle);
} catch(...) {
destroyHandle(handle);
throw;
}
}
~DatabaseConnection() {
destroyHandle(handle);
}
};
23.2 强异常安全
事务模式实现:
cpp复制class Account {
int balance;
mutable std::mutex mtx;
public:
void transfer(Account& to, int amount) {
std::unique_lock lock1(mtx, std::defer_lock);
std::unique_lock lock2(to.mtx, std::defer_lock);
std::lock(lock1, lock2);
if(balance < amount) throw InsufficientFunds();
balance -= amount;
try {
to.balance += amount;
} catch(...) {
balance += amount; // 回滚
throw;
}
}
};
24. 移动语义优化
24.1 完美转发应用
工厂函数示例:
cpp复制template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
return std::unique_ptr<T>(
new T(std::forward<Args>(args)...));
}
24.2 移动感知容器
自定义vector示例:
cpp复制template<typename T>
class Vector {
T* data;
size_t size;
public:
void push_back(const T& value) {
// 拷贝构造新元素
}
void push_back(T&& value) {
// 移动构造新元素
}
// 移动构造函数
Vector(Vector&& other) noexcept
: data(other.data), size(other.size) {
other.data = nullptr;
other.size = 0;
}
};
25. 多线程同步模式
25.1 读写锁应用
shared_mutex使用示例:
cpp复制class ThreadSafeConfig {
std::unordered_map<std::string, int> settings;
mutable std::shared_mutex mtx;
public:
int get(const std::string& key) const {
std::shared_lock lock(mtx);
return settings.at(key);
}
void set(const std::string& key, int value) {
std::unique_lock lock(mtx);
settings[key] = value;
}
};
25.2 无锁编程示例
原子引用计数:
cpp复制template<typename T>
class SharedPtr {
T* ptr;
std::atomic<int>* count;
public:
~SharedPtr() {
if(count && --*count == 0) {
delete ptr;
delete count;
}
}
SharedPtr(const SharedPtr& other)
: ptr(other.ptr), count(other.count) {
++*count;
}
};
26. 嵌入式模式特例
26.1 静态多态应用
CRTP模式示例:
cpp复制template<typename Derived>
class Base {
public:
void interface() {
static_cast<Derived*>(this)->implementation();
}
};
class Derived : public Base<Derived> {
public:
void implementation() {
// 具体实现
}
};
26.2 零成本抽象
表达式模板示例:
cpp复制template<typename Lhs, typename Rhs>
class AddExpr {
const Lhs& lhs;
const Rhs& rhs;
public:
AddExpr(const Lhs& l, const Rhs& r) : lhs(l), rhs(r) {}
double operator[](size_t i) const {
return lhs[i] + rhs[i];
}
};
template<typename Expr>
class Vector {
Expr expr;
public:
double operator[](size_t i) const {
return expr[i];
}
};
27. 元对象协议
27.1 属性系统实现
反射属性示例:
cpp复制class Property {
public:
virtual ~Property() = default;
virtual std::string toString() const = 0;
virtual void fromString(const std::string&) = 0;
};
template<typename T>
class TypedProperty : public Property {
T value;
public:
std::string toString() const override {
return std::to_string(value);
}
void fromString(const std::string& s) override {
std::istringstream iss(s);
iss >> value;
}
};
27.2 命令模式扩展
可撤销操作示例:
cpp复制class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
virtual void undo() = 0;
};
class History {
std::vector<std::unique_ptr<Command>> commands;
size_t current = 0;
public:
void execute(std::unique_ptr<Command> cmd) {
cmd->execute();
commands.resize(current);
commands.push_back(std::move(cmd));
++current;
}
void undo() {
if(current > 0) commands[--current]->undo();
}
};
28. 内存模型深入
28.1 原子操作内存序
内存屏障示例:
cpp复制std::atomic<int> x, y;
int r1, r2;
void thread1() {
x.store(1, std::memory_order_release);
r1 = y.load(std::memory_order_acquire);
}
void thread2() {
y.store(1, std::memory_order_release);
r2 = x.load(std::memory_order_acquire);
}
可能结果分析:
- r1=r2=0 (允许但罕见)
- r1=1,r2=0
- r1=0,r2=1
- r1=r2=1
28.2 无锁队列实现
基于CAS的队列:
cpp复制template<typename T>
class LockFreeQueue {
struct Node {
T value;
std::atomic<Node*> next;
};
std::atomic<Node*> head;
std::atomic<Node*> tail;
public:
void push(T value) {
Node* newNode = new Node{std::move(value)};
Node* oldTail = tail.load();
while(!tail.compare_exchange_weak(oldTail, newNode)) {
oldTail = tail.load();
}
oldTail->next.store(newNode);
}
};
29. 编译器黑魔法
29.1 属性扩展应用
自定义属性示例:
cpp复制[[nodiscard("忽略返回值可能导致内存泄漏")]]
void* allocateMemory(size_t size);
[[gnu::always_inline]]
inline int fastAdd(int a, int b) {
return a + b;
}
29.2 链接期优化
LTO配置示例:
cmake复制# CMake配置
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
# 编译器选项
-flto=thin (Clang)
-flto (GCC)
30. 跨平台开发技巧
30.1 条件编译实践
平台抽象示例:
cpp复制#if defined(_WIN32)
using SocketHandle = SOCKET;
#define INVALID_SOCKET_HANDLE INVALID_SOCKET
#else
using SocketHandle = int;
#define INVALID_SOCKET_HANDLE -1
#endif
class Socket {
SocketHandle handle;
public:
~Socket() {
if(handle != INVALID_SOCKET_HANDLE) {
#if defined(_WIN32)
closesocket(handle);
#else
close(handle);
#endif
}
}
};
30.2 ABI兼容设计
稳定接口示例:
cpp复制// 公开头文件
extern "C" {
struct LibraryHandle;
LibraryHandle* createLibrary();
void processData(LibraryHandle*, const char* input, char* output);
void destroyLibrary(LibraryHandle*);
}
// 内部实现
class LibraryImpl {
// 具体实现细节
};
LibraryHandle* createLibrary() {
return reinterpret_cast<LibraryHandle*>(new LibraryImpl);
}
31. 调试符号处理
31.1 符号还原技巧
addr2line使用:
bash复制addr2line -e executable -f -C 0x401000
31.2 崩溃报告生成
backtrace实现:
cpp复制void printStackTrace() {
void* array[50];
size_t size = backtrace(array, 50);
char** symbols = backtrace_symbols(array, size);
for(size_t i = 0; i < size; ++i) {
std::cerr << symbols[i] << std::endl;
}
free(symbols);
}
32. 构建系统进阶
32.1 模块依赖管理
CMake模块示例:
cmake复制# Find第三方库
find_package(Boost REQUIRED COMPONENTS filesystem system)
# 创建目标
add_library(MyLibrary MODULE
my_library.cpp
)
# 设置依赖
target_link