现代 C++ 与最佳实践

翻译整理自 cppreference - C++ 与 Core Guidelines。

1. 现代 C++ 基本原则

  • RAII:资源即对象
  • 值语义优先:避免过度使用指针
  • 零法则:让编译器自动生成特殊成员函数
  • noexcept 移动:保证 STL 容器性能
  • const 与 constexpr 优先
  • auto + 列表初始化

2. auto 与类型推断

auto x = 42;                              // int
const auto& s = getString();             // const 引用,避免拷贝

for (const auto& item : container) { ... }
auto [k, v] = *map.begin();              // C++17 解构
auto [a, b, c] = std::tuple{1, 2.0, "x"};

3. 列表初始化

int x{0};
std::vector<int> v{1, 2, 3};
struct Point { int x, y; };
Point p{1, 2};

// 检查窄化
int y{3.14};                              // ❌ 编译错误

4. constexpr 与 consteval

constexpr int square(int x) { return x * x; }
consteval int cube(int x) { return x * x * x; }    // C++20,必须编译期求值

int arr[square(5)];
int n = cube(3);

5. 模块 Modules(C++20)

替代 #include,加速编译:

// math.cpp
export module math;

export int add(int a, int b) { return a + b; }

// main.cpp
import math;
int main() { return add(1, 2); }

模块支持仍在主流编译器中逐步完善。

6. 协程 Coroutines(C++20)

#include <coroutine>

struct ReturnObject {
    struct promise_type {
        ReturnObject get_return_object() { return {}; }
        std::suspend_always initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void return_void() {}
        void unhandled_exception() {}
    };
};

ReturnObject hello() {
    co_await std::suspend_always{};
}

C++23 提供 std::generator 简化:

std::generator<int> counter(int n) {
    for (int i = 0; i < n; ++i) co_yield i;
}

7. ranges 与 views

#include <ranges>
namespace v = std::views;

auto r = std::vector{1, 2, 3, 4, 5}
    | v::filter([](int x){ return x % 2 == 0; })
    | v::transform([](int x){ return x * x; });

for (int x : r) std::cout << x;            // 4 16

8. concepts 约束

template <typename T>
concept Addable = requires(T a, T b) { a + b; };

template <Addable T>
T sum(T a, T b) { return a + b; }

9. consteval constinit

constinit int x = 42;                       // 编译期初始化,但运行期可改

10. 工程化建议

头文件

#pragma once
#include <vector>
#include <string>

namespace mylib {
class Engine;
class Car {
public:
    Car();
    void drive();
private:
    std::unique_ptr<Engine> engine_;
};
}

.cpp 实现

#include "car.h"
#include "engine.h"
namespace mylib {
Car::Car() : engine_(std::make_unique<Engine>()) {}
void Car::drive() { ... }
}

编译选项推荐

g++ -std=c++20 -Wall -Wextra -Wpedantic -Wshadow \
    -Wconversion -Wno-unused-parameter \
    -O2 -g -fsanitize=address,undefined \
    prog.cpp -o prog

构建系统

  • CMake:事实标准
  • Bazel:大型项目
  • Meson:易用
  • Conan / vcpkg:包管理

11. 静态检查工具

  • clang-tidy
  • cppcheck
  • Include What You Use
  • sanitizers:ASan、UBSan、TSan、MSan
  • Valgrind
  • gprof / perf

12. 风格与社区规范

参考 Google C++ Style Guide、CppCoreGuidelines、LLVM Coding Standards。

核心要点:

  • 不用 using namespace std; 在头文件
  • 函数名 camelCase 或 snake_case(项目内统一)
  • 成员变量加后缀 _ 或前缀 m_
  • 头文件防卫用 #pragma once
  • 不用 C 风格字符串处理(strcpy 等)

13. 常见陷阱

  • 迭代器失效:v.push_back 后旧迭代器可能失效
  • 未定义行为:有符号溢出、悬空引用、越界
  • 返回临时对象引用:const T& f() { return T(); } 悬空
  • shared_ptr 循环引用:内存泄漏
  • auto 类型推断陷阱:auto x = {1} 是 initializer_list<int>
  • 不安全的多线程:无锁读写共享数据

小结

现代 C++(C++17/20/23)已经远比早期 C++ 简洁安全。掌握 RAII、智能指针、模板、并发,再加上 ranges/concepts/modules/coroutines,可以写出工业级、易维护的代码。