这篇文章深入探讨了 C++ 从 C++98/03 到 C++20 的主要版本演进,并为每个主要特性提供了代码示例和详细的解释。


C++ 的史诗级进化:从基石到现代摩天大楼 (C++98 - C++20 详解,含示例)

C++,这门在软件开发领域屹立数十载的语言,早已不是当年吴下阿蒙。它如同一座不断扩展、持续翻新的宏伟建筑,从 C++98/03 奠定的坚实地基,到 C++11 拔地而起的现代化主体结构,再经过 C++14/17 的精心装修和 C++20 增添的炫酷新翼,如今的 C++ 已然是一座功能强大、结构精妙的现代化摩天大楼。

理解这座“大楼”的建造历程,不仅能让我们欣赏其设计的精妙,更能让我们熟练运用其中的各种“设施”,建造出更稳固、更高效、更舒适的“应用程序房间”。无论你是刚拿到“入住钥匙”的新手,还是已在此“居住”多年的老兵,重新审视 C++ 的进化之路,都将获益匪浅。

本文将详细梳理 C++ 各主要标准版本带来的核心新特性,并通过代码示例展示它们的用法和威力。

C++98/03:奠基时代 —— 经典 C++ 的核心骨架

(发布于 1998年,2003年小幅修订)

这个时代确立了 C++ 的核心范式,至今仍是语言的基础。它提供了强大的底层控制能力和抽象机制。

核心特性回顾 (无新增特性,仅回顾基础):

  • 面向对象: 类 (class), 继承, 多态 (virtual 函数)。
  • 模板 (Templates): 泛型编程,STL 的基础。
  • 标准模板库 (STL): 容器 (vector, map 等), 算法 (sort 等), 迭代器。
  • 异常处理: try/catch/throw
  • 命名空间: namespace 防止命名冲突。
  • RTTI: dynamic_cast, typeid

主要痛点: 手动内存管理 (new/delete) 易错,类型声明冗长,容器初始化繁琐,无标准并发支持,NULL/0 表示空指针有歧义,模板错误信息难懂。

C++11:现代化革命 —— 重塑 C++ 的里程碑

(发布于 2011年)

C++11 是一次全面的现代化升级,旨在解决 C++98/03 的诸多痛点,大幅提升开发体验和代码质量。

主要新特性详解及示例:

  1. auto 类型推导

    • 对比旧版: 无需再写冗长、复杂的类型名,尤其是迭代器。
    • 使用方法:auto 声明变量,编译器自动推导类型。
      #include <vector>
      #include <string>
      #include <map>
      #include <iostream>
      
      int main() {
          auto count = 10; // 推导为 int
          auto pi = 3.14159; // 推导为 double
          auto message = std::string("Hello"); // 推导为 std::string
      
          std::map<int, std::vector<double>> dataMap;
          // ... 填充 dataMap ...
          // 如果不用 auto,迭代器类型非常长!
          auto it = dataMap.find(42); // it 推导为 std::map<...>::iterator
      
          if (it != dataMap.end()) {
              std::cout << "Found key 42" << std::endl;
          }
          return 0;
      }
      
    • 场景: 简化变量声明,提高可读性(当类型明显时)和可维护性。
    • 提升: 大幅减少样板代码。
  2. 基于范围的 for 循环

    • 对比旧版: 告别手动迭代器管理 (begin(), end(), ++it)。
    • 使用方法: for (声明 : 范围)
      #include <vector>
      #include <iostream>
      #include <map>
      
      int main() {
          std::vector<int> numbers = {1, 2, 3, 4, 5};
          std::cout << "Numbers: ";
          for (int n : numbers) { // 简单遍历读取
              std::cout << n << " ";
          }
          std::cout << std::endl;
      
          std::map<std::string, int> ages = {{"Alice", 30}, {"Bob", 25}};
          std::cout << "Ages:" << std::endl;
          for (const auto& pair : ages) { // 使用 const auto& 避免拷贝
              std::cout << " - " << pair.first << " is " << pair.second << std::endl;
          }
      
          std::cout << "Double numbers: ";
          for (auto& n : numbers) { // 使用 auto& 修改元素
              n *= 2;
              std::cout << n << " ";
          }
          std::cout << std::endl;
          return 0;
      }
      
    • 场景: 遍历容器、数组、初始化列表等序列。
    • 提升: 代码更简洁、直观、安全。
  3. Lambda 表达式

    • 对比旧版: 无需定义独立的函数或 Functor 类来实现简单的局部操作。
    • 使用方法: [捕获](参数) -> 返回类型 { 函数体 }
      #include <vector>
      #include <algorithm>
      #include <iostream>
      
      int main() {
          std::vector<int> v = {1, 5, 2, 8, 3};
          int offset = 10;
          int sum_even = 0;
      
          // 1. 无捕获,简单比较器
          std::sort(v.begin(), v.end(), [](int a, int b) { return a < b; });
      
          // 2. 按值捕获 offset
          std::for_each(v.begin(), v.end(), [offset](int x) {
              std::cout << (x + offset) << " ";
          });
          std::cout << std::endl;
      
          // 3. 按引用捕获 sum_even,并在内部修改
          std::for_each(v.begin(), v.end(), [&sum_even](int x) {
              if (x % 2 == 0) {
                  sum_even += x;
              }
          });
          std::cout << "Sum of even numbers: " << sum_even << std::endl; // 输出 10 (2+8)
      
          // 4. 自动推导返回类型
          auto multiply = [](int a, int b) { return a * b; };
          std::cout << "Multiply 3*4: " << multiply(3, 4) << std::endl; // 输出 12
      
          return 0;
      }
      
    • 场景: STL 算法谓词/操作,创建回调,定义局部帮助函数。
    • 提升: 代码更紧凑,逻辑更集中,表达能力强(闭包)。
  4. nullptr

    • 对比旧版: 解决了 NULL/0 的类型歧义。
    • 使用方法:nullptr 代替 NULL0 表示空指针。
      #include <iostream>
      #include <cstddef> // for std::nullptr_t
      
      void print(int x) { std::cout << "print(int): " << x << std::endl; }
      void print(char* p) { std::cout << "print(char*): " << (p ? p : "null") << std::endl; }
      
      int main() {
          print(0);       // 调用 print(int)
          // print(NULL); // 可能编译错误或调用 print(int)
          print(nullptr); // 清晰地调用 print(char*)
          char* my_ptr = nullptr;
          print(my_ptr);  // 调用 print(char*)
          return 0;
      }
      
    • 场景: 任何需要表示或检查空指针的地方。
    • 提升: 类型安全,代码意图明确。
  5. 智能指针 (std::unique_ptr, std::shared_ptr, std::weak_ptr)

    • 对比旧版: 彻底改变手动 new/delete 的模式。
    • 使用方法: 使用 <memory> 头文件中的类管理动态资源。
      #include <memory>
      #include <iostream>
      #include <vector>
      
      struct Resource {
          int id;
          Resource(int i) : id(i) { std::cout << "Resource " << id << " acquired\n"; }
          ~Resource() { std::cout << "Resource " << id << " released\n"; }
      };
      
      // unique_ptr 示例
      std::unique_ptr<Resource> create_resource(int id) {
          return std::unique_ptr<Resource>(new Resource(id)); // C++11 方式
          // return std::make_unique<Resource>(id); // C++14 更好
      }
      
      void use_resource(std::unique_ptr<Resource> res) {
          if (res) std::cout << "Using resource " << res->id << "\n";
      } // res 离开作用域,资源自动释放
      
      // shared_ptr 示例
      void share_resource(std::shared_ptr<Resource> res, const std::string& user) {
          std::cout << user << " is using resource " << res->id << " (use count: " << res.use_count() << ")\n";
      } // res 离开作用域,引用计数减 1
      
      int main() {
          std::cout << "--- unique_ptr ---" << std::endl;
          {
              auto r1 = create_resource(1);
              use_resource(std::move(r1)); // 必须移动所有权
              // r1 现在为空
          } // 资源 1 在 use_resource 结束时释放
      
          std::cout << "\n--- shared_ptr ---" << std::endl;
          std::shared_ptr<Resource> r2 = std::make_shared<Resource>(2); // C++11 推荐方式
          std::cout << "Initial use count: " << r2.use_count() << std::endl;
          auto r3 = r2; // 共享所有权
          std::cout << "After copy, use count: " << r2.use_count() << std::endl;
          share_resource(r2, "User A");
          share_resource(r3, "User B");
          std::cout << "Leaving main scope..." << std::endl;
          // r2 和 r3 离开作用域,引用计数归零,资源 2 释放
          return 0;
      }
      
    • 场景: 管理任何动态分配的资源(内存、文件句柄、锁等)。
    • 提升: 极大地提高了内存安全、异常安全,代码更简洁健壮。
  6. 移动语义与右值引用 (&&)

    • 对比旧版: 避免昂贵的资源拷贝,实现高效的资源转移。
    • 使用方法: 实现移动构造函数和移动赋值运算符,使用 std::move 触发移动。
      #include <vector>
      #include <string>
      #include <utility> // for std::move
      #include <iostream>
      
      class DataHolder {
      public:
          std::vector<int> data;
          DataHolder(size_t size) : data(size) { std::cout << "DataHolder constructed (size " << size << ")\n"; }
          ~DataHolder() { std::cout << "DataHolder destroyed\n"; }
          // 禁用拷贝 (或实现深拷贝)
          DataHolder(const DataHolder&) = delete;
          DataHolder& operator=(const DataHolder&) = delete;
          // 移动构造
          DataHolder(DataHolder&& other) noexcept : data(std::move(other.data)) { // 直接移动 vector 成员
              std::cout << "DataHolder move constructed\n";
          }
          // 移动赋值
          DataHolder& operator=(DataHolder&& other) noexcept {
              data = std::move(other.data); // 直接移动 vector 成员
              std::cout << "DataHolder move assigned\n";
              return *this;
          }
      };
      
      DataHolder create_holder(size_t s) { return DataHolder(s); }
      
      int main() {
          DataHolder h1 = create_holder(1000); // 移动构造 (或 RVO)
          DataHolder h2(2000);
          DataHolder h3 = std::move(h2); // 显式移动构造
          // h2.data 现在为空
          return 0;
      }
      
    • 场景: 实现资源管理类,优化函数参数传递和返回值。
    • 提升: 显著提升性能。
  7. 初始化列表与统一初始化 ({})

    • 对比旧版: 提供统一、简洁的初始化语法。
    • 使用方法: 使用 {} 初始化变量、容器、类对象。
      #include <vector>
      #include <map>
      #include <string>
      
      struct Point { int x; int y; };
      
      int main() {
          int a = 5;       int a_u{5};      // 基本类型
          int arr[] = {1, 2}; int arr_u[]{1, 2}; // 数组
          Point p = {10, 20}; Point p_u{10, 20}; // 聚合体
      
          std::vector<int> v = {1, 3, 5}; // 容器初始化
          std::map<std::string, int> counts = {{"apple", 2}, {"banana", 5}};
      
          // 注意区分构造函数调用
          std::vector<int> v1(10);  // 10 个默认值 (0)
          std::vector<int> v2{10};  // 1 个元素,值为 10
          return 0;
      }
      
    • 场景: 各种初始化场景。
    • 提升: 代码一致性、简洁性,容器初始化方便。
  8. 并发编程支持

    • 对比旧版: 标准库提供了跨平台并发工具。
    • 使用方法: 使用 <thread>, <mutex>, <atomic>, <future> 等。
      #include <thread>
      #include <vector>
      #include <iostream>
      #include <atomic>
      
      std::atomic<int> counter = 0; // 原子计数器,无需锁
      
      void increment() {
          for (int i = 0; i < 10000; ++i) {
              counter++; // 原子操作
          }
      }
      
      int main() {
          std::vector<std::thread> threads;
          for (int i = 0; i < 4; ++i) {
              threads.emplace_back(increment);
          }
          for (auto& t : threads) {
              t.join();
          }
          std::cout << "Final counter: " << counter << std::endl; // 应为 40000
          return 0;
      }
      
    • 场景: 多线程、并行计算、异步任务。
    • 提升: 标准化、可移植的并发能力。
  9. overridefinal

    • 对比旧版: 解决了虚函数重写易错和缺乏继承控制的问题。
    • 使用方法: 在派生类虚函数后加 override,在虚函数或类名后加 final
      struct Base { virtual void draw() const = 0; };
      struct Circle : Base { void draw() const override; }; // 确保重写
      struct SpecialCircle final : Circle { void draw() const override; }; // SpecialCircle 不能被继承
      // struct MoreSpecial : SpecialCircle {}; // 编译错误
      
    • 场景: 继承体系设计。
    • 提升: 代码更健壮,设计意图更明确。
  10. 默认和删除函数 (= default, = delete)

    • 对比旧版: 提供了显式控制特殊成员函数生成或禁用的方法。
    • 使用方法: 在函数声明后加上 = default= delete
      class MyClass {
      public:
          MyClass() = default;            // 使用默认构造
          MyClass(int) = delete;          // 禁止 int 构造
          virtual ~MyClass() = default;   // 使用默认析构(如果是虚的)
          MyClass(const MyClass&) = delete; // 禁止拷贝
          MyClass& operator=(const MyClass&) = delete;
          MyClass(MyClass&&) = default;      // 允许默认移动
          MyClass& operator=(MyClass&&) = default;
      };
      
    • 场景: 控制类的“五/六大特殊成员”,禁止不期望的操作。
    • 提升: 意图清晰,控制精确。
  11. constexpr (C++11 基础版)

    • 对比旧版: 引入编译期函数求值能力。
    • 使用方法:constexpr 修饰变量或函数。函数体限制严格。
      constexpr int MAX_SIZE = 1024;
      constexpr int fib(int n) {
          return (n <= 1) ? n : fib(n-1) + fib(n-2); // C++11 可能需要更简单的实现
      }
      constexpr int fib_5 = fib(5); // 编译期计算 (如果编译器支持且函数符合要求)
      
    • 场景: 定义真常量,简单的编译期计算。
    • 提升: 增强编译期能力。

C++14:精炼与完善 —— 让现代 C++ 更好用

(发布于 2014年)

C++14 主要对 C++11 进行补充和优化,提升易用性。

主要新特性详解及示例:

  1. 通用 Lambda 表达式

    • 对比 C++11: Lambda 参数可以使用 auto
    • 使用方法: [](auto x, auto y) { ... }
      auto print = [](const auto& value) { std::cout << value << " "; };
      print(10);
      print("hello");
      print(3.14);
      
    • 场景: 泛型回调,简化模板代码。
    • 提升: Lambda 更灵活通用。
  2. Lambda 初始化捕获 / 广义 Lambda 捕获

    • 对比 C++11: 捕获列表支持 [var = expr]
    • 使用方法: [p = std::move(ptr), count = get_count()] { ... }
      #include <memory>
      #include <utility> // std::move
      auto uptr = std::make_unique<int>(100);
      // 移动 uptr 到 lambda 的成员 p
      auto lambda = [p = std::move(uptr)]() { return *p; };
      std::cout << lambda() << std::endl; // 输出 100
      // uptr 现在是 nullptr
      
    • 场景: 移动捕获资源,捕获时进行计算。
    • 提升: 解决了 C++11 移动捕获的难题,捕获更强大。
  3. 函数返回类型推导

    • 对比 C++11: 函数返回类型可以直接写 auto
    • 使用方法: auto func(auto param) { return param * 2; }
      template<typename T>
      auto get_half(T value) { // 编译器推导返回 T/2 的类型
          return value / 2;
      }
      auto half_int = get_half(10); // int
      auto half_double = get_half(5.0); // double
      
    • 场景: 简化函数声明,尤其模板函数。
    • 提升: 代码更简洁。
  4. constexpr 函数限制放宽

    • 对比 C++11: 允许 constexpr 函数包含局部变量、if/switch、循环等。
    • 使用方法: 可以写更像普通函数的 constexpr 函数。
      constexpr int sum_upto(int n) {
          int sum = 0;
          for (int i = 1; i <= n; ++i) {
              sum += i;
          }
          return sum; // 可以有局部变量和循环
      }
      constexpr int s5 = sum_upto(5); // 编译期计算 15
      
    • 场景: 更复杂的编译期计算。
    • 提升: constexpr 更实用、易用。
  5. 变量模板

    • 新特性: template<typename T> constexpr T pi = ...;
    • 使用方法: pi<double>, pi<float>
      template<typename T>
      constexpr bool is_integer_type = std::is_integral_v<T>; // is_integral_v 是 C++17 的
      
      static_assert(is_integer_type<int>);
      static_assert(!is_integer_type<double>);
      
    • 场景: 类型相关的常量或变量。
    • 提升: 定义方式更自然。
  6. 二进制字面量 (0b) 与 数字分隔符 (')

    • 新特性: 0b1010, 1'000'000
    • 提升: 提高数字字面量的可读性。
  7. std::make_unique

    • 新库特性: 补齐 C++11 缺失。
    • 使用方法: auto ptr = std::make_unique<T>(args...);
    • 提升: 创建 unique_ptr 的标准、安全方式。

C++17:可用性飞跃 —— 更现代、更便捷

(发布于 2017年)

C++17 进一步提升易用性,并引入了多个强大的标准库组件。

主要新特性详解及示例:

  1. 结构化绑定

    • 新特性: auto [x, y, z] = my_tuple;
    • 使用方法: 从 pair, tuple, struct/class(公共成员)中解包。
      #include <map>
      #include <string>
      #include <tuple>
      #include <iostream>
      
      int main() {
          std::map<int, std::string> users = {{1, "Alice"}, {2, "Bob"}};
          for (const auto& [id, name] : users) { // 直接获取 key 和 value
              std::cout << "ID: " << id << ", Name: " << name << std::endl;
          }
      
          std::tuple<double, char, std::string> result{3.14, 'a', "tuple"};
          auto [d_val, c_val, s_val] = result; // 解包 tuple
          std::cout << d_val << ", " << c_val << ", " << s_val << std::endl;
          return 0;
      }
      
    • 场景: 简化对复合类型成员的访问。
    • 提升: 代码极简,可读性强。
  2. if constexpr

    • 新特性: if constexpr (编译期条件) { ... } else { ... }
    • 使用方法: 在模板中根据类型特性选择性编译代码块。
      #include <iostream>
      #include <string>
      #include <type_traits> // for is_integral_v, is_same_v
      
      template <typename T>
      void print_value(T value) {
          if constexpr (std::is_integral_v<T>) {
              std::cout << "Integral: " << value << std::endl;
          } else if constexpr (std::is_same_v<T, std::string>) {
              std::cout << "String: \"" << value << "\"" << std::endl;
          } else {
              std::cout << "Other type: " << value << std::endl;
          }
      }
      
      int main() {
          print_value(10);     // 输出 Integral: 10
          print_value("hello"); // 输出 Other type: hello (const char*)
          print_value(std::string("world")); // 输出 String: "world"
          print_value(3.14);   // 输出 Other type: 3.14
          return 0;
      }
      
    • 场景: 模板元编程,替代 SFINAE/标签分发。
    • 提升: 极大简化编译期条件代码。
  3. 类模板参数推导 (CTAD)

    • 新特性: std::pair p(1, "hello");
    • 使用方法: 创建模板类对象时省略模板参数。需要构造函数支持或提供推导指引 (deduction guide)。
      #include <vector>
      #include <string>
      #include <mutex> // for lock_guard
      
      int main() {
          std::vector v = {1.0, 2.5, 3.0}; // 推导出 std::vector<double>
          std::pair data("key", 100);     // 推导出 std::pair<const char*, int>
          std::mutex mtx;
          std::lock_guard lock(mtx); // 推导出 std::lock_guard<std::mutex>
          return 0;
      }
      
    • 场景: 简化模板对象创建。
    • 提升: 代码更简洁。
  4. 标准库“三件套”:std::optional, std::variant, std::any

    • 新库特性: 处理可选值、和类型、任意类型。
    • 使用方法:
      #include <optional>
      #include <variant>
      #include <any>
      #include <string>
      #include <iostream>
      
      std::optional<int> maybe_get_int(bool success) {
          if (success) return 42;
          else return std::nullopt; // 表示不存在
      }
      
      struct Visitor { // 用于 variant
          void operator()(int i) { std::cout << "It's an int: " << i; }
          void operator()(const std::string& s) { std::cout << "It's a string: " << s; }
          void operator()(double d) { std::cout << "It's a double: " << d; }
      };
      
      int main() {
          // optional
          if (auto val = maybe_get_int(true); val.has_value()) { // 或直接 if(val)
              std::cout << "Optional value: " << val.value() << std::endl; // 或 *val
          }
      
          // variant
          std::variant<int, std::string, double> my_variant;
          my_variant = "hello";
          std::visit(Visitor{}, my_variant); // 输出 It's a string: hello
          std::cout << std::endl;
          my_variant = 123;
           // C++20 lambda visitor: std::visit([](auto&& arg){ ... }, my_variant);
      
          // any
          std::any anything;
          anything = 10;
          std::cout << "Any holds int: " << std::any_cast<int>(anything) << std::endl;
          try {
              std::cout << std::any_cast<std::string>(anything); // 抛出 std::bad_any_cast
          } catch (const std::bad_any_cast& e) {
              std::cout << "Bad any_cast: " << e.what() << std::endl;
          }
          return 0;
      }
      
    • 场景: 函数返回值、状态表示、存储异构数据。
    • 提升: 类型安全、代码意图清晰。
  5. std::string_view

    • 新库特性: 非拥有性的字符串引用。
    • 使用方法: 接收 const char*, std::string 等作为参数,进行只读操作。
      #include <string_view>
      #include <iostream>
      
      void print_substring(std::string_view sv) {
          std::cout << "Substring: [" << sv << "]\n";
      }
      
      int main() {
          std::string long_str = "This is a rather long string";
          std::string_view view(long_str);
      
          print_substring(view.substr(5, 7)); // 高效创建子串视图 "is a ra"
          print_substring("A C-style literal"); // 直接从字面量创建
          return 0;
      }
      
    • 场景: 处理只读字符串,特别是函数参数,避免不必要的拷贝。
    • 提升: 性能,减少内存分配。
  6. 并行算法

    • 新库特性: std::sort(std::execution::par, ...)
    • 使用方法: 为 STL 算法提供执行策略参数 (seq, par, par_unseq)。
    • 场景: 加速大规模数据处理。
    • 提升: 标准化的并行加速入口。需要编译器和库支持,可能需要链接特定库(如 TBB)。
  7. 文件系统库 (<filesystem>)

    • 新库特性: 跨平台文件操作。
    • 使用方法: fs::path, fs::exists, fs::is_directory, fs::create_directory, fs::remove 等。
      #include <filesystem>
      #include <iostream>
      namespace fs = std::filesystem;
      
      int main() {
          fs::path current = fs::current_path();
          fs::path new_dir = current / "my_test_dir";
          fs::create_directory(new_dir);
          std::cout << "Directory created: " << new_dir << std::endl;
          fs::remove(new_dir);
          std::cout << "Directory removed." << std::endl;
          return 0;
      }
      
    • 场景: 文件、目录管理。
    • 提升: 标准化、可移植的文件系统操作。

C++20:再次飞跃 —— 引入基础性变革

(发布于 2020年)

C++20 是又一个引入颠覆性特性的大版本,显著改变了泛型编程、异步编程和代码组织方式。

主要新特性详解 (重点“四大特性”):

  1. 概念 (Concepts)

    • 新语言特性: concept, requires 关键字。
    • 使用方法: 定义类型约束,并在模板声明中使用。
      #include <concepts>
      #include <vector>
      #include <iostream>
      
      template<typename T>
      concept Incrementable = requires(T x) { ++x; x++; }; // 要求支持前置和后置自增
      
      template<Incrementable T> // 约束 T 必须满足 Incrementable
      void increment_twice(T& value) {
          ++value;
          value++;
      }
      
      struct NonIncrementable {};
      
      int main() {
          int i = 0;
          increment_twice(i); // OK, int 满足
          std::cout << i << std::endl; // 输出 2
      
          double d = 1.0;
          increment_twice(d); // OK, double 满足
          std::cout << d << std::endl; // 输出 3.0
      
          // NonIncrementable ni;
          // increment_twice(ni); // 编译错误!不满足 Incrementable 概念
          return 0;
      }
      
    • 场景: 模板编程,提高类型约束的清晰度和编译错误友好性。
    • 提升: 革命性改善模板编程体验。
  2. 模块 (Modules)

    • 新语言特性: export module, import
    • 使用方法: 定义模块接口 (.cppm 实验性) 和实现,使用 import 导入。
      // ---- my_module.cppm (假设) ----
      export module my_module;
      export int add(int x, int y) { return x + y; }
      // ---- main.cpp (假设) ----
      import my_module;
      int main() { return add(2, 3); }
      
    • 场景: 大型项目代码组织。
    • 提升(理论): 编译速度、封装性、消除宏污染。依赖工具链支持。
  3. 协程 (Coroutines)

    • 新语言特性: co_await, co_yield, co_return
    • 使用方法: 定义协程函数(返回特定类型,如 generator, task),使用 co_ 关键字实现暂停/恢复。
      #include <iostream>
      #include <coroutine> // 低层支持
      // #include <generator> // C++23 标准库,或使用第三方库
      
      // (需要一个 generator 实现,这里是伪代码)
      /*
      generator<int> count_upto(int n) {
          for (int i = 0; i < n; ++i) {
              co_yield i; // 产生值并暂停
          }
      }
      int main() {
          for(int x : count_upto(5)) { // 每次循环恢复协程
              std::cout << x << " "; // 输出 0 1 2 3 4
          }
          std::cout << std::endl;
          return 0;
      }
      */
      int main() { 
          std::cout << "C++20 Coroutines need library support.\n"; 
          return 0;
      }
      
    • 场景: 异步编程、生成器、状态机。
    • 提升: 用同步风格编写异步代码,简化复杂流程。依赖库支持。
  4. 范围库 (Ranges)

    • 新库特性: <ranges>, std::views, 范围版算法。
    • 使用方法: 对容器直接调用算法,用 | 组合视图。
      #include <vector>
      #include <ranges>
      #include <iostream>
      #include <algorithm> // for std::ranges::sort
      
      namespace views = std::views;
      namespace ranges = std::ranges;
      
      int main() {
          std::vector<int> data = {1, 8, 2, 7, 3, 6, 4, 5};
      
          auto query = data | views::filter([](int n){ return n > 3; })
                            | views::transform([](int n){ return n * n; })
                            | views::take(3); // 取前 3 个结果
      
          std::cout << "Query results: ";
          for(int x : query) { // 惰性求值
              std::cout << x << " "; // 输出 64 49 36
          }
          std::cout << std::endl;
      
          // 范围版排序
          ranges::sort(data);
          std::cout << "Sorted data: ";
          for(int x : data) std::cout << x << " ";
          std::cout << std::endl;
      
          return 0;
      }
      
    • 场景: 数据处理流水线,简化算法调用。
    • 提升: 声明式数据处理,代码更简洁、可读性强,惰性求值可能带来性能优势。

C++20 其他重要特性:

  • 三路比较运算符 (<=>): auto result = obj1 <=> obj2;
  • constexpr 增强: 编译期 vectorstring 成为可能。
  • 格式化库 (<format>): std::string s = std::format("Hello, {}! Count: {}", "world", 42);
  • <span>: void process(std::span<const int> data);
  • jthread: std::jthread t(func); // 析构时自动 join

C++23 及未来:持续前行

(C++23 已发布)

C++23 继续带来改进,例如:

  • std::expected: std::expected<int, ErrorCode> func();
  • std::print: std::print("Value: {}\n", 42);
  • Ranges 增强: 更多视图和算法。
  • 模块改进。
  • if consteval: 编译期执行的 if
  • mdspan: 多维数组视图。
  • move_only_function: 只能移动的函数包装器。

C++26 也在稳步推进中,未来可期!

结语:成为现代 C++ 开发者

C++ 的进化是一部精彩的技术演进史。现代 C++ 通过引入一系列强大的语言和库特性,极大地改善了开发体验、代码安全性和程序性能。

从 C++11 的智能指针、Lambda、auto,到 C++14 的完善,再到 C++17 的可用性飞跃,以及 C++20 的四大核心变革,每一个版本都值得我们去学习和应用。

拥抱现代 C++,意味着用更少的代码做更多的事,写出更安全、更高效、更易于维护的程序。无论你的 C++ 之旅处于哪个阶段,持续学习和实践这些新特性,都将让你在这座不断成长的“编程摩天楼”里更加游刃有余。


Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐