C++26:反射、内存安全、契约和新的异步模型
Source: Hacker News
C++26 标准草案现已完成,Herb Sutter 报道,他是长期的 C++ 专家,也是 ISO C++ 标准委员会的前任主席。最终草案引入了反射,提升了内存安全性且无需重写代码,新增了带有前置条件和后置条件的契约以及新的断言语句,并建立了统一的并发与并行框架。
反射
反射是一种机制,正如 Sutter 所解释的那样,为开发者提供了 C++ 内部机制的钥匙(观看视频),使语言能够自我描述并生成代码,从而为元编程提供坚实的基础。符合 C++ 的精神,反射不带任何运行时开销。
一个基本示例展示了反射如何实现一种用于声明 C++ 接口的专用语法:
class(interface) IFoo {
int f();
void g(std::string);
};
//-- 将会被翻译成“传统”写法:
class IFoo {
public:
virtual int f() = 0;
virtual void g(std::string) = 0;
virtual ~IFoo() = default;
IFoo() = default;
protected:
IFoo(IFoo const&) = default;
void operator=(IFoo const&) = default;
};
interface 抽象是 cppfront——一个编译到纯 ISO C++ 的编译器 的一部分,Sutter 创建它是为了提供一种更快的方式来实验提案。cppfront 还包含诸如 copyable(表示具有拷贝/移动构造/赋值的类型)、ordered(使用 operator<=> 定义全序类型)、union(带名称的标签联合)、regex 等抽象。
通过将许多原本需要专门语言特性的新功能转化为可复用的编译期库,反射可以简化 C++ 的未来演进——设计更快、测试更易、从第一天起即可跨平台使用。
内存安全
C++26 在内存安全方面带来了显著改进。这些变化消除了读取未初始化局部变量时的未定义行为,并为大多数标准库类型(包括 vector、span、string 和 string_view)提供了边界安全。这些增强功能已经在 Apple 和 Google 的生产环境中部署,覆盖了数亿行 C++ 代码。
- 仅在 Google,新的安全机制已经修复了超过 1,000 个 bug,预计每年可防止 1,000–2,000 个 bug,并将生产环境的段错误率降低了 30 %。
- 这些收益仅通过使用新编译器重新编译现有代码即可实现;只有七个案例需要开发者通过细粒度 API 选择退出内存安全。
合约
C++26 引入了合约,以将 防御式编程 引入语言,提升功能安全性和内存安全性。合约允许开发者表达在方法执行期间不得被违反的前置条件和后置条件。它们还可以在函数声明中放置断言,使调用者和静态分析工具能够看到。
C++ 提供了四种处理合约违规的方式:
- ignore – 什么也不做。
- observe – 在运行时报告违规。
- enforce – 终止程序。
- quick enforce – 快速终止且不提供诊断信息。
此外,原生断言机制取代了 C 的 assert 宏,提供了一种更为集成的方式来强制不变式。
Concurrency and Parallelism
C++26 引入了 std::execution 作为一个框架,用于表达和控制并发与并行。三个主要抽象是 调度器(schedulers)、发送器(senders)和 接收器(receivers),它们可以通过一组可定制的异步算法进行组合。std::execution 设计上能够与 C++20 协程无缝协作,并且使编写使用 结构化(严格的生命周期嵌套)并发与并行的程序更为容易,从而通过构造实现无数据竞争的执行。
Compiler Support
两大主流 C++ 编译器 GCC 和 Clang 已经在标准化过程中实现了大部分 C++26 特性,这些特性很快就会进入主线发行版。