C++17 和 C++20 新特性


C++17 新特性

C++17(2017 年发布)引入了许多实用功能,改进语言的表达力和标准库的可用性。

语言特性

  1. 结构化绑定(Structured Bindings)

    • 允许解构 tuple、pair 或结构体到多个变量。
    • 示例:
      1
      2
      std::pair<int, std::string> p{1, "hello"};
      auto [id, value] = p; // id=1, value="hello"
    • 用途:简化多返回值处理。
  2. if 和 switch 初始化语句

    • 在 if/switch 中初始化变量,限制作用域。
    • 示例:
      1
      2
      3
      if (auto it = map.find(key); it != map.end()) {
      return it->second;
      }
    • 用途:代码更紧凑,减少作用域污染。
  3. 内联变量(Inline Variables)

    • 允许在头文件中定义内联静态变量。
    • 示例:
      1
      inline static int counter = 0; // 多翻译单元共享
    • 用途:简化全局常量或静态变量定义。
  4. 折叠表达式(Fold Expressions)

    • 简化变参模板的递归处理。
    • 示例:
      1
      2
      template<typename... Args>
      auto sum(Args... args) { return (args + ...); }
    • 用途:优雅处理可变参数模板。
  5. constexpr if

    • 编译期条件分支。
    • 示例:
      1
      2
      3
      4
      5
      template<typename T>
      auto get_value(T t) {
      if constexpr (std::is_integral_v<T>) return t * 2;
      else return t;
      }
    • 用途:优化模板代码,减少分支开销。
  6. 类模板参数推导(CTAD)

    • 自动推导类模板参数。
    • 示例:
      1
      std::pair p{1, 2.0}; // 推导为 std::pair<int, double>
    • 用途:简化模板类实例化。

标准库

  1. std::optional

    • 表示可能为空的值。
    • 示例:
      1
      2
      std::optional<int> opt = 42;
      if (opt) std::cout << *opt; // 42
    • 用途:安全处理可能不存在的值。
  2. std::variant

    • 类型安全的联合体。
    • 示例:
      1
      2
      std::variant<int, std::string> v = "hello";
      std::visit([](auto&& x) { std::cout << x; }, v);
    • 用途:替代 union,类型安全。
  3. std::any

    • 存储任意类型的值。
    • 示例:
      1
      2
      std::any a = 42;
      int x = std::any_cast<int>(a);
    • 用途:动态类型场景。
  4. std::filesystem

    • 文件系统操作库。
    • 示例:
      1
      2
      std::filesystem::path p = "file.txt";
      if (std::filesystem::exists(p)) { /* ... */ }
    • 用途:跨平台文件操作。
  5. 并行算法

    • 标准算法支持并行执行。
    • 示例:
      1
      2
      std::vector<int> v(1000);
      std::sort(std::execution::par, v.begin(), v.end());
    • 用途:利用多核提升性能。

C++20 新特性

C++20(2020 年发布)是 C++ 的一次重大更新,引入了模块、概念、协程等变革性特性。

语言特性

  1. 模块(Modules)

    • 替代头文件,改进编译速度和封装。
    • 示例:
      1
      2
      3
      4
      5
      export module math;
      export int add(int a, int b) { return a + b; }
      // 使用
      import math;
      int main() { return add(1, 2); }
    • 用途:减少头文件依赖,加速编译。
  2. 概念(Concepts)

    • 约束模板参数,增强类型检查。
    • 示例:
      1
      2
      3
      4
      template<typename T>
      concept Integral = std::is_integral_v<T>;
      template<Integral T>
      T square(T x) { return x * x; }
    • 用途:提高模板代码可读性和错误提示。
  3. Lambda 增强

    • 支持无状态 lambda 在 constexpr、显式模板参数。
    • 示例:
      1
      2
      auto id = []<typename T>(T x) { return x; };
      constexpr int x = []{ return 42; }();
    • 用途:更灵活的 lambda 应用。
  4. Ranges 库

    • 提供范围视图和管道操作。
    • 示例:
      1
      2
      3
      std::vector<int> v{1, 2, 3, 4};
      auto even = v | std::views::filter([](int x) { return x % 2 == 0; });
      for (int x : even) std::cout << x; // 2 4
    • 用途:函数式编程风格,简化迭代。
  5. 协程(Coroutines)

    • 支持暂停和恢复函数执行。
    • 示例:
      1
      2
      3
      generator<int> count(int n) {
      for (int i = 0; i < n; ++i) co_yield i;
      }
    • 用途:异步编程、生成器。
  6. consteval 和 constinit

    • consteval:强制编译期执行。
    • constinit:确保静态变量初始化。
    • 示例:
      1
      2
      consteval int square(int x) { return x * x; }
      constinit int global = 42;
    • 用途:优化编译期计算,控制初始化。
  7. 三路比较(Spaceship Operator)

    • operator<=> 自动生成比较运算符。
    • 示例:
      1
      2
      3
      struct Point { int x, y;
      auto operator<=>(const Point&) const = default;
      };
    • 用途:简化比较逻辑。

标准库

  1. std::span

    • 轻量视图,表示连续内存视图。
    • 示例:
      1
      2
      3
      void print(std::span<int> s) {
      for (int x : s) std::cout << x;
      }
    • 用途:安全访问连续数据。
  2. std::bit_cast

    • 类型安全的字节级转换。
    • 示例:
      1
      2
      float f = 3.14f;
      uint32_t u = std::bit_cast<uint32_t>(f);
    • 用途:低级数据转换。
  3. std::format

    • 格式化字符串库。
    • 示例:
      1
      std::string s = std::format("Hello, {}!", "world");
    • 用途:更安全、现代化的字符串格式化。
  4. std::source_location

    • 获取调用位置信息。
    • 示例:
      1
      2
      3
      void log(std::source_location loc = std::source_location::current()) {
      std::cout << loc.file_name() << ":" << loc.line();
      }
    • 用途:日志记录。
  5. 日历和时区(Calendar/Timezone)

    • 支持日期时间操作。
    • 示例:
      1
      2
      3
      using namespace std::chrono;
      auto now = std::chrono::system_clock::now();
      auto date = std::year_month_day{std::floor<std::chrono::days>(now)};
    • 用途:跨平台处理时间。

比较与选择

  • C++17:实用性强,适合过渡项目,特性如结构化绑定、std::optional 立即提升代码质量。
  • C++20:更现代化,模块、概念、协程适合新项目,但编译器支持(如 GCC 10+、Clang 10+)和生态成熟度需考虑。