从C++98到C++20
-
- C++ 的史诗级进化:从基石到现代摩天大楼 (C++98 – C++20 详解,含示例)
-
- C++98/03:奠基时代 —— 经典 C++ 的核心骨架
- C++11:现代化革命 —— 重塑 C++ 的里程碑
- C++14:精炼与完善 —— 让现代 C++ 更好用
- C++17:可用性飞跃 —— 更现代、更便捷
- C++20:再次飞跃 —— 引入基础性变革
- C++23 及未来:持续前行
- 结语:成为现代 C++ 开发者
这篇文章深入探讨了 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::stringstd::map<int, std::vector<double>> dataMap;
// … 填充 dataMap …
// 如果不用 auto,迭代器类型非常长!
auto it = dataMap.find(42); // it 推导为 std::map<…>::iteratorif (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; // 输出 12return 0;
} - 场景: STL 算法谓词/操作,创建回调,定义局部帮助函数。
- 提升: 代码更紧凑,逻辑更集中,表达能力强(闭包)。
nullptr
- 对比旧版: 解决了 NULL/0 的类型歧义。
- 使用方法: 用 nullptr 代替 NULL 或 0 表示空指针。#include <iostream>
#include <cstddef> // for std::nullptr_tvoid 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 离开作用域,引用计数减 1int 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 更灵活通用。
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: 函数返回类型可以直接写 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 - 场景: 简化函数声明,尤其模板函数。
- 提升: 代码更简洁。
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 更实用、易用。
变量模板
- 新特性: 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_vtemplate <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_guardint 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; // 输出 2double 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::sortnamespace 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++ 之旅处于哪个阶段,持续学习和实践这些新特性,都将让你在这座不断成长的“编程摩天楼”里更加游刃有余。
评论前必须登录!
注册