C++ 的史诗级进化:从C++98到C++20
C++ 的史诗级进化:从C++98 - C++20 详解,含示例
从C++98到C++20
这篇文章深入探讨了 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 的诸多痛点,大幅提升开发体验和代码质量。
主要新特性详解及示例:
-
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; }
- 场景: 简化变量声明,提高可读性(当类型明显时)和可维护性。
- 提升: 大幅减少样板代码。
-
基于范围的
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; }
- 场景: 遍历容器、数组、初始化列表等序列。
- 提升: 代码更简洁、直观、安全。
- 对比旧版: 告别手动迭代器管理 (
-
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 算法谓词/操作,创建回调,定义局部帮助函数。
- 提升: 代码更紧凑,逻辑更集中,表达能力强(闭包)。
-
nullptr
- 对比旧版: 解决了
NULL
/0
的类型歧义。 - 使用方法: 用
nullptr
代替NULL
或0
表示空指针。#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; }
- 场景: 任何需要表示或检查空指针的地方。
- 提升: 类型安全,代码意图明确。
- 对比旧版: 解决了
-
智能指针 (
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; }
- 场景: 管理任何动态分配的资源(内存、文件句柄、锁等)。
- 提升: 极大地提高了内存安全、异常安全,代码更简洁健壮。
- 对比旧版: 彻底改变手动
-
移动语义与右值引用 (
&&
)- 对比旧版: 避免昂贵的资源拷贝,实现高效的资源转移。
- 使用方法: 实现移动构造函数和移动赋值运算符,使用
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; }
- 场景: 实现资源管理类,优化函数参数传递和返回值。
- 提升: 显著提升性能。
-
初始化列表与统一初始化 (
{}
)- 对比旧版: 提供统一、简洁的初始化语法。
- 使用方法: 使用
{}
初始化变量、容器、类对象。#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; }
- 场景: 各种初始化场景。
- 提升: 代码一致性、简洁性,容器初始化方便。
-
并发编程支持
- 对比旧版: 标准库提供了跨平台并发工具。
- 使用方法: 使用
<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; }
- 场景: 多线程、并行计算、异步任务。
- 提升: 标准化、可移植的并发能力。
-
override
和final
- 对比旧版: 解决了虚函数重写易错和缺乏继承控制的问题。
- 使用方法: 在派生类虚函数后加
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 {}; // 编译错误
- 场景: 继承体系设计。
- 提升: 代码更健壮,设计意图更明确。
-
默认和删除函数 (
= 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; };
- 场景: 控制类的“五/六大特殊成员”,禁止不期望的操作。
- 提升: 意图清晰,控制精确。
-
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 进行补充和优化,提升易用性。
主要新特性详解及示例:
-
通用 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 更灵活通用。
- 对比 C++11: Lambda 参数可以使用
-
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 移动捕获的难题,捕获更强大。
- 对比 C++11: 捕获列表支持
-
函数返回类型推导
- 对比 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
- 场景: 简化函数声明,尤其模板函数。
- 提升: 代码更简洁。
- 对比 C++11: 函数返回类型可以直接写
-
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
更实用、易用。
- 对比 C++11: 允许
-
变量模板
- 新特性:
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>);
- 场景: 类型相关的常量或变量。
- 提升: 定义方式更自然。
- 新特性:
-
二进制字面量 (
0b
) 与 数字分隔符 ('
)- 新特性:
0b1010
,1'000'000
。 - 提升: 提高数字字面量的可读性。
- 新特性:
-
std::make_unique
- 新库特性: 补齐 C++11 缺失。
- 使用方法:
auto ptr = std::make_unique<T>(args...);
- 提升: 创建
unique_ptr
的标准、安全方式。
C++17:可用性飞跃 —— 更现代、更便捷
(发布于 2017年)
C++17 进一步提升易用性,并引入了多个强大的标准库组件。
主要新特性详解及示例:
-
结构化绑定
- 新特性:
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; }
- 场景: 简化对复合类型成员的访问。
- 提升: 代码极简,可读性强。
- 新特性:
-
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/标签分发。
- 提升: 极大简化编译期条件代码。
- 新特性:
-
类模板参数推导 (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; }
- 场景: 简化模板对象创建。
- 提升: 代码更简洁。
- 新特性:
-
标准库“三件套”:
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; }
- 场景: 函数返回值、状态表示、存储异构数据。
- 提升: 类型安全、代码意图清晰。
-
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; }
- 场景: 处理只读字符串,特别是函数参数,避免不必要的拷贝。
- 提升: 性能,减少内存分配。
-
并行算法
- 新库特性:
std::sort(std::execution::par, ...)
- 使用方法: 为 STL 算法提供执行策略参数 (
seq
,par
,par_unseq
)。 - 场景: 加速大规模数据处理。
- 提升: 标准化的并行加速入口。需要编译器和库支持,可能需要链接特定库(如 TBB)。
- 新库特性:
-
文件系统库 (
<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 是又一个引入颠覆性特性的大版本,显著改变了泛型编程、异步编程和代码组织方式。
主要新特性详解 (重点“四大特性”):
-
概念 (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; }
- 场景: 模板编程,提高类型约束的清晰度和编译错误友好性。
- 提升: 革命性改善模板编程体验。
- 新语言特性:
-
模块 (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); }
- 场景: 大型项目代码组织。
- 提升(理论): 编译速度、封装性、消除宏污染。依赖工具链支持。
- 新语言特性:
-
协程 (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; }
- 场景: 异步编程、生成器、状态机。
- 提升: 用同步风格编写异步代码,简化复杂流程。依赖库支持。
- 新语言特性:
-
范围库 (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
增强: 编译期vector
和string
成为可能。- 格式化库 (
<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++ 之旅处于哪个阶段,持续学习和实践这些新特性,都将让你在这座不断成长的“编程摩天楼”里更加游刃有余。
更多推荐
所有评论(0)