C++ 是一门兼顾高性能与抽象能力的编程语言。自 1998 年第一个国际标准发布以来,C++ 每隔几年就会更新一次标准,每次更新都带来新的语法特性和标准库功能。
本文将从 C++98 一直讲到 C++23,逐一介绍各版本的主要语言和库特性。
C++98 —— 奠基之作
模板
C++98 正式引入了类模板和函数模板,使得泛型编程成为可能。开发者可以编写与类型无关的代码,从而实现更高的复用性。
标准模板库(STL)
STL 成为 C++98 的核心组成部分,提供了 vector
、list
、map
、set
、string
等容器,以及 algorithm
中的排序、查找、遍历等算法。
异常处理
C++98 标准化了异常处理机制,使用 try
、catch
和 throw
进行错误处理,使得程序能够以结构化的方式应对运行时错误。
命名空间
引入 namespace
关键字,允许开发者将代码组织在不同的命名空间中,避免名字冲突。
面向对象机制
C++98 完善了面向对象编程的支持,包括虚函数、多重继承、运算符重载和函数重载。
示例代码(STL 与异常处理)
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> v = {3, 1, 4};
std::sort(v.begin(), v.end());
for (int x : v) std::cout << x << " ";
try {
throw std::runtime_error("error");
} catch (const std::exception& e) {
std::cout << "\nCaught: " << e.what();
}
}
C++03 —— 小修小补
值初始化
C++03 改进了值初始化语义,使得 T()
形式的初始化会将内置类型初始化为零值。
模板改进
模板机制在 C++03 中得到增强,修复了边界情况的处理问题,使得模板在更多场景下能够正确工作。
标准库修正
std::vector<bool>
的实现细节得到修正,避免了部分实现中的不一致性。
export 关键字
C++03 引入了 export
关键字,意图支持模板的分离编译,但几乎没有编译器实现,后续在 C++11 中被废弃。
示例代码(值初始化)
#include <iostream>
int main() {
int x{}; // 值初始化为 0
std::cout << x;
}
C++11 —— 现代 C++ 的起点
auto 类型推导
auto
关键字允许编译器根据初始化表达式自动推导变量类型,减少了冗长的类型声明。
nullptr
引入 nullptr
关键字,提供了类型安全的空指针,取代了传统的 NULL
。
范围 for 循环
新增范围 for 循环语法,可以直接遍历容器或数组,简化了迭代器的使用。
Lambda 表达式
Lambda 表达式允许在函数内部定义匿名函数对象,极大地提升了函数式编程的便利性。
constexpr
constexpr
关键字允许在编译期进行常量计算,提升了性能并增强了类型安全。
右值引用与移动语义
C++11 引入右值引用和移动语义,避免了不必要的拷贝,提高了资源管理的效率。
static_assert
static_assert
提供了编译期断言机制,可以在编译阶段检查条件是否成立。
强类型枚举
enum class
提供了强类型枚举,避免了枚举值的隐式转换。
统一初始化语法
花括号 {}
被统一用于初始化,提供了一致的初始化方式。
可变参数模板
C++11 支持可变参数模板,使得函数和类可以接受任意数量的模板参数。
智能指针
标准库引入了 std::unique_ptr
和 std::shared_ptr
,简化了动态内存管理,避免了内存泄漏。
多线程库
C++11 将多线程支持纳入标准,提供了 std::thread
、std::mutex
、std::future
等工具。
无序容器
新增 std::unordered_map
和 std::unordered_set
,基于哈希表实现,提供了高效的查找性能。
正则表达式
标准库 <regex>
提供了正则表达式支持,用于字符串匹配和搜索。
元组
std::tuple
提供了多值返回和组合数据的能力。
示例代码(Lambda、右值引用、多线程)
#include <iostream>
#include <thread>
#include <vector>
int main() {
auto add = [](int a, int b){ return a+b; };
std::cout << "Lambda: " << add(2,3) << "\n";
std::vector<int> a = {1,2,3};
std::vector<int> b = std::move(a); // 移动而非拷贝
std::cout << "Moved size: " << b.size() << "\n";
std::thread t([]{ std::cout << "Thread running\n"; });
t.join();
}
C++14 —— 小幅增强
泛型 Lambda
C++14 允许 Lambda 表达式的参数使用 auto
,从而支持泛型 Lambda。
std::make_unique
新增 std::make_unique
,为智能指针提供了安全的工厂函数,避免了内存泄漏风险。
二进制字面量
支持二进制字面量,例如 0b1010
,使得二进制数表示更加直观。
数字分隔符
引入单引号 '
作为数字分隔符,例如 1'000'000
,提高了大数字的可读性。
返回类型推导
函数返回类型可以自动推导,简化了函数定义。
constexpr 增强
constexpr
的能力增强,支持更多语句和逻辑,使得编译期计算更加强大。
示例代码(泛型 Lambda、make_unique)
#include <iostream>
#include <memory>
int main() {
auto add = [](auto a, auto b){ return a+b; };
std::cout << "Generic lambda: " << add(1,2.5) << "\n";
auto p = std::make_unique<int>(42);
std::cout << "Unique ptr: " << *p << "\n";
}
C++17 —— 工业级增强
结构化绑定
C++17 引入结构化绑定,可以直接将 pair
或 tuple
拆解为多个变量。
if constexpr
if constexpr
提供了编译期条件分支,避免了无效代码的实例化。
内联变量
内联变量允许在头文件中定义全局变量而不引发多重定义。
折叠表达式
折叠表达式简化了可变参数模板的展开,减少了模板代码的复杂性。
属性扩展
C++17 增加了 [[nodiscard]]
和 [[maybe_unused]]
等属性,提升了代码的可读性和安全性。
std::optional
std::optional
用于表示可选值,避免了使用特殊值表示缺失的情况。
std::variant
std::variant
提供了类型安全的联合体,可以存储多种类型中的一种。
std::any
std::any
可以存储任意类型的值,提供了类型擦除的能力。
并行算法
标准库算法支持并行执行策略,通过 std::execution
提供并行化能力。
文件系统库
std::filesystem
提供了跨平台的文件和目录操作。
std::string_view
std::string_view
提供了轻量级的字符串视图,避免了不必要的拷贝。
std::byte
std::byte
提供了类型安全的字节表示,避免了使用 char
或 unsigned char
的歧义。
示例代码(结构化绑定、optional、filesystem)
#include <iostream>
#include <optional>
#include <tuple>
#include <filesystem>
int main() {
auto [x,y] = std::make_pair(1,2);
std::cout << "Structured binding: " << x << "," << y << "\n";
std::optional<int> v = 42;
if (v) std::cout << "Optional: " << *v << "\n";
for (auto& p : std::filesystem::directory_iterator(".")) {
std::cout << "File: " << p.path() << "\n";
}
}
C++20 —— 里程碑式更新
Concepts
C++20 引入 Concepts,用于约束模板参数,提升了泛型编程的可读性和安全性。
Ranges
Ranges 提供了基于范围的算法和视图,支持链式组合,简化了数据处理。
协程
协程机制使得异步编程更加自然,支持 co_await
、co_yield
和 co_return
。
模块
模块系统提供了比头文件更高效的编译单元组织方式,减少了编译时间。
constexpr 增强
constexpr
的能力进一步增强,几乎支持所有语句,包括动态分配和虚函数调用。
三路比较运算符
引入 <=>
运算符,简化了比较操作,自动生成关系运算符。
consteval
consteval
定义立即函数,保证在编译期执行。
constinit
constinit
保证变量在编译期完成静态初始化,避免未定义行为。
std::span
std::span
提供了对数组和容器的非拥有视图,简化了数据访问。
std::format
std::format
提供了现代化的格式化输出,取代了 printf
风格的接口。
std::jthread
std::jthread
是自动 join 的线程,简化了线程管理。
std::stop_token
std::stop_token
提供了线程取消机制,支持协作式终止。
日历与时区库
<chrono>
扩展了日历和时区支持,提供了更丰富的时间处理能力。
示例代码(Concepts、Ranges、format)
#include <concepts>
#include <ranges>
#include <vector>
#include <iostream>
#include <format>
template<std::integral T>
T add(T a, T b) { return a+b; }
int main() {
std::cout << "Concepts: " << add(1,2) << "\n";
std::vector<int> v = {1,2,3,4,5};
for (int x : v | std::ranges::views::filter([](int n){ return n%2==0; }))
std::cout << "Even: " << x << "\n";
std::cout << std::format("Hello {}!\n", "world");
}
C++23 —— 实用增强
std::expected
std::expected
提供了比异常更轻量的错误处理方式,返回值中同时包含结果或错误信息。
std::print
std::print
简化了输出操作,提供了类似 Python 的打印接口。
Ranges 扩展
Ranges 库得到扩展,增加了 views::zip
、views::chunk
等新视图,提升了组合能力。
多维下标运算符
多维下标运算符 operator[]
支持多个参数,简化了多维数组访问。
模块和协程完善
模块和协程在实现和标准化上更加成熟,提升了可移植性和稳定性。
constexpr 动态内存分配
constexpr
支持动态内存分配,提升了编译期计算能力。
std::flat_map 和 std::flat_set
标准库增加了 std::flat_map
和 std::flat_set
,它们基于排序向量实现,适合小规模数据的高效存储。
示例代码(expected、print、ranges 扩展)
#include <expected>
#include <print>
#include <ranges>
#include <vector>
#include <iostream>
std::expected<int,std::string> parse(const std::string& s){
try{ return std::stoi(s); }
catch(...){ return std::unexpected("bad"); }
}
int main() {
auto r = parse("42");
if (r) std::print("Expected: {}\n", *r);
else std::print("Error: {}\n", r.error());
std::vector<int> a={1,2,3}, b={4,5,6};
for (auto [x,y] : std::views::zip(a,b))
std::cout << "Sum: " << x+y << "\n";
}
时间线速览
- C++98/03:奠基,STL 成型
- C++11:现代 C++ 的起点(lambda、智能指针、多线程)
- C++14:小幅改进(泛型 lambda、make_unique)
- C++17:工业级增强(optional、variant、filesystem)
- C++20:里程碑(concepts、ranges、coroutines、modules)
- C++23:实用增强(expected、print、ranges 扩展)
- C++26:未来(反射、模式匹配、并发增强)
C++ 的演进始终围绕 性能、抽象能力、可维护性 三个目标。
如果你是初学者,可以从 C++11 开始学习,因为它是现代 C++ 的起点。 在实际项目中,建议尽量使用 C++17 或更高版本,因为它们在语法和库上都更强大、更易用。 关注 C++20/23/26,能让你跟上语言发展的最新趋势。