C++标准更新内容一览:这些新特性你用上了吗?

最近在写公司的一个老项目,代码还是基于 C++11 的,编译器一升级,突然发现一堆警告。点开一看,不少写法已经被新标准标记为过时了。这才意识到,C++ 标准这几年更新得挺勤快,光是近十年就有 C++14、C++17、C++20、C++23 几个大版本,每个都带了不少实用的改进。

C++14:小修小补,但很贴心

很多人觉得 C++14 只是 11 的“补丁包”,其实它有几个特别顺手的功能。比如泛型 Lambda,以前写 Lambda 得指定参数类型,现在可以直接用 auto:

[] (auto x, auto y) { return x + y; }

还有返回值推导,函数不用再啰嗦地写返回类型了:

auto add(int a, int b) { return a + b; }

C++17:真正开始“现代化”

从这一版开始,C++ 写起来明显轻松了。最常用的是结构化绑定,处理 pair 或 tuple 特别方便:

std::map<std::string, int> scores = {{"Alice", 95}, {"Bob", 87}};
for (const auto& [name, score] : scores) {
    std::cout << name << ": " << score << std::endl;
}

还有 if constexpr,编译期判断不再依赖模板特化,逻辑更清晰:

template <typename T>
void process(T value) {
    if constexpr (std::is_pointer_v<T>) {
        std::cout << *value;
    } else {
        std::cout << value;
    }
}

C++20:终于有了模块和概念

头文件包含慢、命名冲突多?C++20 引入了模块(module),可以这样写:

export module math;
export int add(int a, int b) { return a + b; }

// 导入使用
import math;

另一个重磅是 concept,让模板参数有约束,编译错误信息不再天书一样:

template <typename T>
concept Integral = std::is_integral_v<T>;

Integral auto add(Integral auto a, Integral auto b) {
    return a + b;
}

C++23:更简单,更安全

最新版 C++23 加了个特别实用的功能——std::expected,用来处理可能出错的操作,比返回 bool 或抛异常更直观:

std::expected<int, std::string> divide(int a, int b) {
    if (b == 0) {
        return std::unexpected("Division by zero");
    }
    return a / b;
}

// 使用
auto result = divide(10, 2);
if (result) {
    std::cout << "Result: " << *result << std::endl;
} else {
    std::cout << "Error: " << result.error() << std::endl;
}

另外,像 std::print 这种简化输出的工具也来了,告别 std::cout 的 << 操作符嵌套。

这些更新不是为了炫技,而是真正在降低出错概率、提升开发效率。如果你还在用老标准,不妨从局部试点,比如先在工具类里用结构化绑定或 auto 推导,慢慢过渡,代码会清爽很多。