关于 Rust、C 和 C++ 的讨论,互联网上已经太多了。有人认为 Rust 会取代 C/C++,也有人认为 C/C++ 永远不会死;还有人把 Rust 视为社区炒作,或认为 C++ 终将因复杂而被淘汰。Rust 的学习曲线、C 作为系统语言的地位,以及 C++ 的存量生态,也常被拿来作为论据。这些说法有些成立,有些并不成立,也有一些只是情绪表达。

若从软件工业、系统工程、安全工程、语言生态和个人职业发展的角度来看,事情远比 “取代” 或 “不会取代” 复杂。更准确的问题并不是 Rust 会不会让 C 和 C++ 消失,因为两者背后有数十年的存量代码,以及操作系统、数据库、浏览器、游戏引擎、嵌入式、音视频、图形、科学计算、工业软件、金融系统、芯片 SDK、驱动和基础库。真正值得问的是:未来新项目立项时,C 和 C++ 是否仍是默认首选?Rust 能否让原本会使用 C / C++ 的新系统项目转向?哪些领域会被分流,哪些地方即使抛开历史原因也很难被分流?作为 C++ 开发者,又该如何面对这种变化?本文围绕这些问题展开。

Rust 的目标不是让 C / C++ 消失

很多关于 Rust 的争论,一开始就偏离了重点。有人认为 Rust 不可能取代 C/C++,因为 Linux、Windows、OpenSSL、ffmpeg、LLVM、Unreal、Chrome、数据库和嵌入式系统都不会重写。这没有问题。但更现实的目标,并不是将所有 C/C++ 存量系统重写一遍,而是减少 C 和 C++ 在新增项目中的默认地位,让未来更多系统工程的新项目不再首先选择它们。

过去,项目的语言选择往往遵循一条熟悉的路径:追求性能时选 C++,需要底层控制或贴近硬件时选 C,需要操作系统组件、驱动、数据库、存储或网络栈时选 C/C++,不想引入 GC 时也常常选 C++。Rust 想改变的正是这条默认链条。它并不是说 C/C++ 会在明天消失,而是在问:如果今天从零开始编写一个系统组件,尤其是安全敏感、面向网络或处理不可信输入的组件,为什么还要默认选择 C/C++?当行业心智从 “系统项目默认 C/C++,除非有理由不用”,转为 “系统项目先考虑 Rust,除非有理由必须使用 C/C++”,Rust 在新增项目上的目标便已实现。因此,这场竞争并不是消灭存量,而是争夺新增。

成熟资产和新项目不是一回事

安全领域很能说明成熟资产与新项目的差别。仅因 Rust 具有内存安全特性,就断言 OpenSSL 应被 rustls 替代,并不足以构成完整判断。选择 TLS 库时,语言只是其中一项因素;项目负责人还会考察它经历过多少真实攻击与多年审计,是否支持各种平台并能与客户端、服务器和证书系统互操作,是否具备合规认证路径、漏洞响应机制和长期维护者,以及它是否已在银行、云厂商、浏览器、操作系统和大型企业的真实环境中部署过。出问题时由谁负责,同样是选择的一部分。

OpenSSL 虽然以 C 编写,也出现过严重漏洞,但它被攻击、审计、修复和大规模部署过,并在各种输入与环境中积累了经验。年轻的 Rust TLS 库即便内存安全特性更强,也不自动意味着整体安全风险更低。TLS 库还涉及协议状态机、证书链和 X.509 解析、密码套件选择、降级与重放防护、随机数使用、常数时间实现、侧信道、API 易用性、平台兼容、硬件加速、合规认证、长期审计、供应链和真实世界互操作性。Rust 主要处理语言层面的内存安全,不能自动保证这些方面没有漏洞,也不能立即补足十几二十年的审计信用。

因此,把成熟稳定的 OpenSSL 换成一个年轻 Rust 库,并不会只因 “Rust 更安全” 就成为必然选择。但从零编写新的安全组件时,情况会不同。证书、图片、字体、压缩格式和网络协议解析器,以及 sandbox 边界、WebAssembly runtime、身份认证网关、密钥管理、安全扫描、边界代理、VPN 和新协议栈,都需要处理大量不可信输入。此时继续选择更容易出现 use-after-free、buffer overflow、double free、越界访问和数据竞争的语言,需要给出明确理由。更准确地说,OpenSSL 未必会被 rustls 替代,但新的同类安全资产未必还会以 C 为默认实现语言。

Rust 的内存安全是否已经足够重要

也应避免把 Rust 的安全能力说得过满。Rust 在语言层面主要解决内存安全和一部分并发安全问题,例如 use-after-free、double free、buffer overflow、越界读写、悬垂指针、迭代器失效、部分未初始化内存、数据竞争和资源生命周期混乱。这些确实是 C / C++ 安全漏洞中的重要来源,浏览器、操作系统和网络服务中的许多高危漏洞都与它们有关。

但 Rust 不会自动解决密码算法、协议设计、认证流程、证书验证、权限模型和状态机的正确性,也不能保证常数时间实现、侧信道防护、供应链安全、依赖治理、API 设计、系统配置、运维、合规和审计。因此,说 Rust 主要解决内存安全,大体上是成立的。与此同时,OptionResult、enum、模式匹配、所有权、借用、移动语义、trait 和类型状态建模,确实能减少一部分安全工程错误。它们可以区分已验证与未验证的证书,限制握手前后的状态混用,避免明文密钥被任意复制,并把资源释放、跨线程共享、错误处理和权限 token 的使用方式表达得更明确。

这些能力并不等同于密码学正确性,但属于安全工程的一部分。Rust 不能自动让安全组件正确,却能使许多危险错误无法通过编译,并帮助开发者明确安全状态和资源边界。面对 OpenSSL、BoringSSL、LibreSSL、libsodium 等成熟项目,年轻 Rust 库的这些优势也未必能压过长期部署和审计形成的信用。更可能的情况是,成熟的 C / C++ 安全基础设施继续存在;新增安全边界组件更多考虑 Rust、Go、Java、C# 等内存安全语言;关键密码库仍需经过长期部署、审计、攻击和修复,才能建立信用。

为什么很多语言挑战 C / C++ 失败?

C / C++ 难以被挑战,并不是因为它们没有缺点。内存安全、UB、构建系统、包管理、C++ 的语言复杂度、模板报错、ABI 和大型工程维护,长期都是实际问题,安全漏洞的代价也很高。但它们同时具备一组少见的能力:性能可以接近硬件上限,没有 GC,资源控制相对可预测,能够操作内存布局并贴近 ABI,也能用于操作系统、驱动、数据库、浏览器、游戏引擎、裸机和嵌入式环境。C ABI 是事实上的跨语言接口标准,平台支持广泛,存量和生态庞大,调试器、profiler、sanitizer 与编译器工具链也已经成熟。

因此,挑战 C/C++ 的语言不能只说明自己更安全或更易写,还必须回答一系列工程问题:是否有 GC,能否用于裸机和内核,能否控制内存布局并与 C ABI 交互,性能能否接近 C/C++,资源释放是否可预测,能否渐进迁移,工具链是否足以支撑大型工程,以及大型组织是否愿意采用。历史上的许多语言都没有同时回答好这些问题。

Java 和 C#

Java 和 C# 都取得了广泛采用,承接了大量原本可能由 C++ 编写的企业、服务器、桌面和平台应用,但没有真正取代 C / C++ 的系统编程位置。两者都有 GC 和运行时,不适合裸机、内核、驱动或硬实时场景;内存布局的控制也不够直接,ABI 与硬件之间隔着一层,延迟和资源释放并不完全由程序员直接决定。这并非否定 Java 或 C#,而是说明它们主要覆盖应用层和企业层,对 C++ 的影响是局部的。

Go

Go 在云原生、网络服务、平台工程和基础设施工具中也很成功。Docker、Kubernetes、Prometheus、etcd 和 Terraform 等生态使它有了广泛影响力。其简洁的语言设计、较快的编译速度、方便部署、goroutine、标准库和较为一致的工程体验,吸引了许多团队;不少原本可能用 C++ 编写的服务端基础设施项目因此转向 Go。

不过 Go 仍有边界。它带有 GC,底层控制力弱于 C/C++/Rust,类型系统相对保守,也不适合内核、驱动、裸机、极端低延迟和大量依赖精细内存布局的项目。它的性能足以覆盖许多场景,但并不追求 C/C++ 的极限模型。因此,Go 更接近面向云基础设施的简化选择,而不是 C++ 的直接替身。

D

D 语言曾经非常像 “更好的 C++”。它有:系统编程能力;高性能;现代语法;模板;可选 GC;C 互操作。但 D 没有成为主流。原因包括:生态没有起来;标准库和编译器路线分裂;社区规模有限;企业背书不足;没有形成不可替代的核心叙事;C11 之后 C 自己吸收了一部分现代特性;没有像 Rust 那样抓住 “内存安全” 这个政策级、组织级驱动力。D 是一个典型例子:技术上很有野心,但没有形成产业势能。

Ada/SPARK

Ada 和 SPARK 在高可靠领域非常强。它们适合:航空航天;军工;高可靠系统;需要形式化验证的项目。但它们没有成为通用系统编程主流。原因包括:社区小;工具链和生态相对封闭;普通互联网公司采用少;学习和行业门槛高;开源世界存在感有限;语言形象偏专用、高可靠、政府 / 军工。Ada 是局部成功,但不是广义替代。

Swift

Swift 很现代,也有不错性能。但它主要成功在 Apple 生态。它的问题是:心智上绑定 Apple;Linux/服务器/嵌入式/内核生态弱;系统编程社区心智不如 Rust;没有形成 “C/C++ 安全替代者” 的强叙事。Swift 是成功语言,但不是广义 C/C++ 挑战者。

Zig

Zig 是值得关注的语言。它强调简洁、无 GC 和显式控制,C 互操作与交叉编译体验较好,也适合底层、小系统和工具链场景;相较 Rust,其学习曲线通常更平缓。两者的差异在于,Zig 更接近现代化的 C,而 Rust 更强调内存安全的系统编程。Zig 没有 Rust 那样的强所有权和借用模型,也没有将内存安全作为核心叙事。因此,它可能会进入一部分希望获得更现代工具链与表达方式的 C 场景,但未必取代 Rust 在内存安全系统工程中的定位。

Rust 为什么特殊?

Rust 之所以被认为是 C / C++ 的强力挑战者,不是因为它语法时髦,也不是因为它社区热闹,而是因为它第一次比较完整地回答了系统程序员最在意的几个问题。

Rust 没有 GC

这是关键。GC 并非没有价值,它适合大量应用开发;但对内核、驱动、bootloader、部分嵌入式和硬实时系统、低延迟交易系统、游戏引擎关键路径、数据库存储引擎、密码库和基础库而言,额外运行时与不可直接控制的回收行为都可能成为限制。系统 runtime 本身也难以依赖另一个复杂 runtime。Rust 的特殊之处在于,它不依靠 GC 管理内存,而是在编译期尽量证明内存使用合法,因此能够进入 C / C++ 长期覆盖的核心场景。

Rust 保留了系统编程能力

Rust 能完成许多传统 C / C++ 所承担的工作,包括控制内存分配、区分栈与堆、使用自定义 allocator、零成本抽象、指针操作、SIMD、FFI、no_std、裸机和嵌入式开发,以及操作系统组件、驱动、WebAssembly runtime、数据库、编译器和网络栈。许多底层操作仍需使用 unsafe,但其思路是将不可避免的危险操作限制在明确的边界内,让安全代码成为默认。相比之下,C / C++ 的更大一部分语言空间都可能出现不安全操作;这种边界差异对大型团队和安全审计有实际影响。

Rust 攻击的是结构性问题

C / C++ 的内存安全问题不能只依靠开发者更谨慎来解决。静态分析、code review、sanitizers、fuzzing、RAII、smart pointers、Core Guidelines、现代 C++、编码规范、安全子集和生命周期分析都很有用,却没有从根本改变语言模型:悬垂指针、越界访问、重复释放、错误别名、UB 和并发数据竞争仍可能出现。Rust 的吸引力在于,它不只是要求程序员更加小心,而是让大量错误无法通过编译。这也解释了为什么企业、安全团队和政府机构越来越重视内存安全语言;这一政策与产业背景,是以往的挑战者并未同时具备的条件。

Rust 可以渐进进入 C / C++ 系统

Rust 不需要你一次性重写几百万行 C++。它可以走现实路线:老核心继续 C / C++;新模块用 Rust;新解析器用 Rust;新安全边界组件用 Rust;新 CLI 工具用 Rust;新存储组件用 Rust;新网络代理用 Rust;通过 FFI 和原系统连接;慢慢扩大 Rust 代码比例。这就是 Rust 最危险的地方。它不需要马上替换整个系统。它只需要在每一次新增模块时赢一点点。长期看,新增项目份额就会变化。

Cargo 和工具链体验是巨大优势

C / C++ 的工程体验长期很痛苦:Makefile;CMake;Autotools;Bazel;vcpkg;Conan;系统包管理器;平台 SDK;编译器差异;链接问题;ABI 问题;依赖版本问题;跨平台构建问题。C++ 程序员往往已经习惯痛苦了,但新团队、新项目、新人并不一定愿意继续承受。Rust 的 Cargo、crates.io、rustup、rustfmt、clippy、测试、文档生成这一整套工具链,对于新项目吸引力很强。Rust 不只是语言安全,它的现代工程体验也在分流 C++。

Rust 会不会被 “程咬金” 截胡?

可能。Rust 不是终点,也不是完美语言。它有很多现实问题:学习曲线陡;borrow checker 难;生命周期让新人崩溃;编译速度慢;async 复杂;trait / generic 系统有时过于绕;宏系统强但复杂;unsafe 仍然不可避免;C++ 互操作不够自然;ABI 稳定性不足;某些领域生态薄弱;crate 依赖树和供应链治理有风险。所以未来出现一个新语言,说:我有 Rust 的无 GC、性能和内存安全,但语法更简单、编译更快、异步更自然、C++ 互操作更好。这是完全可能的。潜在 “程咬金” 有几类。

Zig

Zig 可能会在一些 C 的生态位上成功。它简洁、直接、无 GC、C 互操作强、交叉编译体验好。但 Zig 不以强内存安全作为核心卖点。所以它更可能成为:

更现代、更舒服、更工程化的 C。而不是全面取代 Rust 的安全系统语言。

Carbon / Cpp2

Carbon 和 Cpp2 这类东西,本质上想给 C++ 找一条现代化迁移路线。如果它们能做到:与 C++ 无缝互操作;迁移成本低;性能保持;工具链成熟;大厂支持;安全性显著提升;保留 C++ 生态资产。那它们会对 Rust 形成很大威胁。因为很多公司最大的问题不是 “Rust 好不好”,而是:我已经有 500 万行 C++,怎么办?如果有一种语言能作为 C++ 的自然继承者,并且迁移成本远低于 Rust,那它当然有吸引力。但目前看,这条路还非常不确定。C++ 的历史包袱太重。要在保留兼容性的同时显著改善内存安全,极其困难。

Mojo

Mojo 更偏 AI、高性能计算、Python 生态加速。它如果成功,可能会影响:AI 基础设施;数值计算;GPU kernel;Python 性能扩展;高性能计算。Mojo 未必正面替代 Rust,而可能直接吃掉一些 Rust 本来可能进入的 AI / HPC 新领域。

安全 C++

C++ 社区不是什么都不做。未来可能会有:lifetime profile;safety profiles;静态分析强化;sanitizers 常态化;C++ Core Guidelines;编译器强制安全模式;受限 C++ 子集;Herb Sutter 的 Cppfront / Cpp2;Google、Microsoft 等推动安全 C++。如果 C++ 能在不破坏生态的情况下显著降低内存安全风险,Rust 的上升速度会受影响。但这很难。因为 C++ 最大的问题是兼容性。它不能轻易禁止大量历史写法。它的自由和混乱是同一个硬币的两面。

但 Rust 不会被 “突然” 截胡

即使未来出现更好的语言,Rust 也不会突然消失。语言生态变化很慢。一个新语言要经历:

爱好者使用;小工具验证;中型项目采用;大公司试点;工具链成熟;生态形成;招聘市场出现;关键基础设施采用;安全审计和长期部署积累;形成产业信任。这个周期通常是 5 到 15 年。Rust 现在已经不是玩具语言。它已经进入:

Linux kernel;Android;Windows 的部分安全讨论和组件;AWS;Cloudflare;Google;Microsoft;Mozilla;WebAssembly 生态;Firecracker;Wasmtime;TiKV;Vector;Deno;Ruff;uv;SWC;ripgrep;fd;bat;starship;Zed 等工具和项目。Rust 已经占住了一个很强的心智:Rust = memory safety + no GC + systems programming + performance + C/C++ alternative。后来者要赢,不能只是更好一点,必须好很多,并且还要花十年级别积累信任。所以更可能的未来不是 Rust 被某个语言一击打倒,而是:Rust 还没完全吃掉 C/C++,就被 Zig、Carbon、Mojo、安全 C++、Go 等从不同方向分流。不是一门语言统一天下,而是多语言重新划分生态位。

C / C++ 被分流是必然

C/C++ 的一部分市场,本来就是历史偶然和路径依赖。很多项目过去用 C++,不是因为 C++ 最适合,而是因为:当时没有 Rust;Go 还没成熟;Java/C# 有 GC;Python 太慢;需要性能;需要系统接口;团队习惯;行业默认。但很多项目其实不需要 C++ 那种极端自由,比如:普通业务系统;普通网络服务;大量工具;安全扫描器;数据处理管道;日志系统;包管理器;新的 CLI;新的代理服务;普通后端;部分中间件;部分系统组件。这些项目需要的是:足够性能;可维护性;安全性;好部署;好招聘;好工具链;少踩坑。它们并不需要:全局裸指针自由;到处 reinterpret_cast;手动释放;Undefined Behavior;复杂模板怪物;任意内存别名;任意对象生命周期 hack。过去很多项目是 “用大炮打蚊子”:只是想要性能,却被迫承受 C++ 的复杂性和内存风险。所以这些领域被 Rust、Go、Java、C#、Swift、Python、TypeScript 分流是必然的。C++ 会失去很多本来不该属于它的新增项目。这不是坏事。反而说明语言生态变成熟了。

C 和 C++ 仍有很难被分流的东西

虽然 C / C++ 会被分流,但不能说它们只靠历史活着。即使不谈存量生态,它们也有语言模型层面的硬优势。而且 C 和 C++ 的硬优势不一样。

C :极薄底层边界能力

C 最强的地方,不是它安全,不是它现代,而是它足够薄。C 接近一种 “可移植汇编”。它适合表达:函数;指针;数值;struct;内存布局;调用约定;系统边界;硬件寄存器;ABI。C 的最硬优势之一是 C ABI。几乎所有语言都能调用 C:Rust 调 C;Python 调 C;Java 通过 JNI 调 C;C# P/Invoke 调 C;Go 调 C;Swift 调 C;Zig 调 C;Lua/Ruby/Node 原生扩展也大量围绕 C ABI。C ABI 是事实上的跨语言最低公分母。相比之下:C++ ABI 复杂;Rust ABI 不稳定;Go/Java/C# 有运行时模型;Swift ABI 有平台语境;Python 不是系统 ABI。所以未来即使一个库内部用 Rust 写,对外接口很可能仍然是 C ABI,比如:

1
2
int library_do_something(const char* input, size_t len);

C 可能不再是实现语言首选,但会长期是接口语言、边界语言、胶水语言。

C 适合最小运行时和裸机

有些地方你什么都没有:没有堆;没有线程;没有文件系统;没有动态链接器;没有异常;没有标准库;没有完整 runtime;甚至还在启动阶段,比如:bootloader;内核早期初始化;裸机固件;芯片 bring-up;runtime stub;freestanding 环境;极小 MCU 程序;硬件测试程序。C 在这里非常自然。Rust 也有 no_std,Zig 也能做,但 C 的语言模型天生就很薄。你基本知道一段 C 会生成什么样的机器码,需要什么运行时支持。这在极底层仍然很有价值。

C 适合硬件寄存器

硬件手册里经常直接给 C 宏或 C 结构体,比如:

1
2
3
4
#define UART_BASE 0x40001000
#define UART_DR (*(volatile uint32_t *)(UART_BASE + 0x00))
#define UART_SR (*(volatile uint32_t *)(UART_BASE + 0x04))

这种东西用 C 写就是自然。C 当然有坑:padding;alignment;endianness;bit field 可移植性;strict aliasing;volatile 语义复杂。但它和硬件文档、寄存器、协议头、DMA buffer、boot protocol 的心智距离很近。因此 C 很难从这些底层边界彻底退出。

C++:复杂高性能工程表达力

C++ 的硬优势和 C 不一样。C 是薄、简单、贴近 ABI。C++ 是复杂、强大、能承载大型高性能抽象系统。它的核心能力是:

零成本抽象 + 极端自由 + 能容纳现实工程的混乱。

零成本抽象仍然非常强

C++ 可以写很高级的抽象,同时努力不为没用到的东西付运行时成本。它有:templates;constexpr;concepts;RAII;move semantics;inline;operator overloading;expression templates;CRTP;policy-based design;allocator-aware containers;ranges;metaprogramming。这些东西复杂,但高手可以用它们构建非常强的高性能库。比如 Eigen 这种线性代数库,就大量依赖 expression templates,把数学表达式压到编译期优化。游戏引擎、图形库、数值库、HPC 库、数据库执行引擎,也经常需要这种 “高层抽象 + 低层性能” 的混合能力。Rust 也有零成本抽象,而且内存安全更强。但 C++ 在某些领域的表达自由度和历史积累非常深。尤其是当你需要把高级抽象、手写内存管理、平台特化和老接口全部揉在一起时,C++ 仍然很顺手。

C++ 的 RAII 表达非常成熟

C++ 的 RAII 是极其强大的思想。资源不只是内存,还包括:文件句柄;socket;mutex;GPU resource;texture;command buffer;transaction;lock guard;mmap;database handle;temporary arena;scope rollback。C++ 用构造函数和析构函数表达资源生命周期,非常自然。Rust 的 ownership 和 Drop 在这方面也很强,甚至更安全。但 C++ 的 RAII 与对象模型结合得非常深,很多工程师已经形成了很成熟的资源管理习惯。在一些复杂系统中,C++ 的灵活性仍然非常高。

C++ 特别适合共享可变状态

很多现代安全语言都希望你说清楚:谁拥有对象;谁借用对象;谁能修改对象;生命周期多长;是否跨线程;是否共享;是否可变。这是好事。但很多真实系统就是非常不规则:游戏场景图;GUI object tree;编译器 IR;数据库执行计划;ECS;observer list;callback registry;plugin system;cache;双向引用;parent-child 互指;图结构;异步任务图。C++ 对这些东西非常宽容。你可以混用:裸指针;unique_ptrshared_ptrweak_ptr;引用;handle;ID;arena;intrusive container;object pool。Rust 也能做,但往往需要:Rc<RefCell<T>>Arc<Mutex<T>>;arena;generational index;slotmap;unsafe;重新设计所有权结构;更数据导向的架构。Rust 最终可能让结构更清晰,但前期架构约束更强。而 C++ 允许你直接表达很多 “不干净但现实” 的结构,比如一些很经典但复杂的数据格式。

“歪门邪道” 的价值

有些项目特别能说明 C / C++ 的生命力。ffmpeg 就是典型。ffmpeg 不是一个普通的视频库。它是几十年:

奇怪格式;历史兼容;坏文件;手写 SIMD;汇编优化;硬件编解码;跨平台;性能压榨;容错;黑魔法;工程妥协。堆出来的系统怪物。这种东西不是 Rust 写不出来,而是:它的价值不只是代码本身,而是几十年现实世界的脏活和经验。Rust 的语言安全当然有吸引力,但要替代 ffmpeg 这种工程怪物,不是语法更现代就够了。类似的还有一些科学计算库、数值库、HPC 库。它们可能有:Fortran 历史接口;C ABI;BLAS/LAPACK 生态;手写汇编;AVX/AVX2/AVX-512;GPU kernel;CUDA;编译器特定优化;数值稳定性经验;奇怪矩阵布局;cache blocking;SIMD trick;平台特化;“歪门邪道但有效” 的数学和工程技巧。这些项目往往不是 “干净的系统工程”,而是 “极端性能工程 + 历史兼容 + 数学技巧 + 硬件细节” 的混合物。C/C++ 很适合这种混沌。

歪门邪道的人也是生态位

Heng Li 那句调侃[1] 很有意思:

Am I switching to Rust? Not in the near future. I enjoy the freedom of shooting myself in the foot.

翻译过来就是:我会转 Rust 吗?短期不会。我享受开枪打自己脚的自由。这句话乍看像是在开玩笑,但它抓住了 C / C++ 的一种文化心理。有些程序员确实喜欢,或者确实需要:控制每一个字节;看汇编;手写 allocator;手动 SIMD;对齐优化;利用平台细节;写 JIT;做二进制 patch;维护 ABI;绕过抽象层;和编译器斗智斗勇;为 2% 性能提升重写内存布局;在危险边缘跳舞。他们不是不知道危险。他们的态度是:我知道危险,但我需要这种自由。我愿意承担代价。Rust 对这类人有时会显得管得太多。Rust 的哲学是:危险可以做,但你要进入 unsafe,并且把边界圈起来。C++ 的哲学更像:世界是开放的,你自己负责。对大型组织来说,Rust 的哲学更健康。但对某些顶级底层工程师、性能工程师、科学计算库作者、视频编解码专家、游戏引擎黑魔法师来说,C++ 的自由仍然非常有吸引力。而纵观那些改变人类或者创造历史的项目,不少就出自这样一群人之手。

C++ 的真正哲学

C++ 之父 Bjarne Stroustrup 有一段话很值得反复看:

Someone who claims to have a perfect programming language is either a salesman or a fool, or both. [2]

声称自己有完美编程语言的人,要么是销售,要么是傻瓜,或者两者都是。他还说过:

My aim was for C++ to become the second best language for many things.

他的目标不是让 C++ 成为所有事情的最佳语言,而是成为很多事情的第二好语言。这句话一开始会让很多人震惊:

为什么不追求第一?

但这是非常现实的语言哲学。因为:

There can’t be a language that’s best for everything and everybody.

不可能有一门语言对所有事、所有人都是最佳。每个领域理论上都可以有最理想的 DSL: SQL 适合关系查询;shader language 适合 GPU shader;Verilog/VHDL 适合硬件描述;regex 适合文本模式;Python 适合胶水和 AI 上层;Lua 适合嵌入脚本;MATLAB/R 适合统计和数值原型;Rust 适合安全系统组件;C 适合 ABI 和裸机;C++ 适合复杂高性能框架。但这些理想语言之间有一个问题:它们怎么互操作?如果每个领域都用自己的小语言,系统怎么构建?怎么调试?怎么部署?怎么共享内存?怎么组合成一个大型产品?Bjarne 的回答是:需要一个通用框架,C++ 就试图成为这样的框架。C++ 的强项不是每个点都最优雅,而是它可以承载各种风格:C 风格;面向对象;泛型;函数式;模板元编程;编译期计算;宏;RAII;异常;无异常;RTTI;无 RTTI;裸指针;智能指针;手写内存池;嵌入式 DSL;平台 hack。C++ 里面可以长出:Eigen;Qt;Unreal;LLVM;Boost;ranges;coroutine framework;allocator framework;expression templates;游戏对象系统;GUI 框架;编译期 DSL;GPU 抽象层。这些东西不一定美,但它们能装下现实世界的复杂性。所以 C++ 的哲学可以概括为:我不保证你不受伤,但我给你最大表达空间。Rust 的哲学则是:我尽量不让你受伤,但你要按照我的规则表达问题。这不是简单的先进和落后。这是两种工程哲学。

未来格局

未来较可能的格局既不是 Rust 消灭 C++,也不是 C++ 完全不受影响,而是 C / C++ 在新增项目中被系统性分流:Rust 在新系统工程中扩大采用,C++ 保留复杂高性能场景,C 则继续承担底层边界和 ABI 的角色。

Rust 的主战场

Rust 较容易进入那些需要接近 C / C++ 的性能和控制力,又不希望继续承担其内存安全风险的新系统项目。例如新网络基础设施、代理和网关、存储与数据库组件、安全边界组件、各类解析器、虚拟化和容器基础设施、WebAssembly runtime、CLI、构建工具、包管理器和开发工具链,以及部分 OS 组件、中高端嵌入式、云基础设施和高性能服务。在这些场景中,Rust 会逐渐成为常被优先评估的选项。

C++ 的保留地

C++ 仍会广泛用于游戏引擎、图形渲染、音视频编解码、ffmpeg 一类长期演化的项目、复杂高性能库、HPC、科学计算底层、ML runtime、物理仿真、CAD/CAE/EDA、高频交易、浏览器部分模块、工业软件和大型桌面软件。对于需要大量底层处理、平台特化和历史兼容的系统,它的表达自由度和抽象能力仍有实际价值。

C 的保留地

C 会长期存在于 C ABI、libc、syscall 接口、bootloader、裸机、芯片 SDK、内核极底层、语言 runtime、动态库接口、嵌入式小固件、硬件寄存器定义、平台胶水和 freestanding 环境中。它在许多项目中的角色,可能会从主要实现语言逐步更多转向底层公共边界语言。

其他语言的领地

许多领域本就不必由 Rust 或 C++ 主导。企业业务常使用 Java、C# 或 Kotlin,云服务常使用 Go、Java 或 C#;AI 上层与数据分析多依赖 Python、R 和 SQL,前端使用 TypeScript,移动端使用 Swift、Kotlin 或 Dart,脚本自动化使用 Python 和 Shell。Mojo、Triton、CUDA 等也可能在 AI / HPC 中形成新的路径。Rust、C++ 和其他现有或未来的语言,都不可能是所有问题的最佳答案,这也印证了 “没有一门语言适合所有事情和所有人”。

作为 C++ 开发者真正应该学什么?

这个讨论最终会落到职业发展上。对 C++ 开发者而言,若能力只停留在语言语法、STL、少量模板和业务逻辑,而缺少系统、性能、内存模型、ABI、工具链、安全、并发和其他语言生态的认识,选择空间可能会变窄。这并不只与 Rust 有关;多年来,Java、Go、C#、Rust、Python 和 TypeScript 已在不同场景中承接了原本可能由 C++ 完成的项目。学习 Rust 是一种补充方式,而 C++ 开发者更有价值的能力通常位于复杂系统和性能工程的深处。

学 Rust,补内存安全思维

即使主要使用 C++,学习 Rust 也有帮助,并不意味着必须转向 Rust。它会促使开发者重新理解所有权、借用、生命周期、移动语义、别名、共享可变性、数据竞争,以及 API 如何表达所有权和缩小 unsafe 的边界。再回头写 C++ 时,便会更自然地审视对象由谁拥有、谁只是观察者、谁可以修改、生命周期何时结束、引用是否可能悬垂,以及 unique_ptrshared_ptrspanstring_view 或 move-only 对象是否更合适。Rust 对 C++ 开发者的意义,不只是多掌握一门语言,也是建立更严格的所有权和生命周期意识。

深挖 C++ 的王牌区能力

C++ 开发者可以强化性能工程、系统编程、内存模型、并发、ABI、编译链接、工具链、crash debugging、sanitizers、fuzzing、profiling、SIMD、allocator、cache locality、lock-free、NUMA、CPU pipeline 和 branch prediction 等能力。关键不在于掌握多少语法,而在于能解释并处理具体问题:代码为何变慢,cache miss 或 false sharing 从何而来,哪里可能触发 UB,线上 core dump、链接失败和 ABI 不兼容如何发生,allocator 为何造成性能抖动,锁为何成为瓶颈,数据结构为何不适合 CPU cache。这些能力决定了复杂工程中的处理范围。

选一个行业纵深

C++ 最好与一个具体的技术领域结合。例如,音视频会涉及 ffmpeg、codec、container format 与 SIMD;游戏需要面对引擎、ECS、渲染、资源和脚本系统;数据库、网络、编译器、图形、ML runtime、嵌入式、低延迟系统和科学计算也各有其底层问题。C++ 的能力往往在深入这些复杂系统之后才会显现出来。

形成 T 型能力

横向上,需要理解不同语言适合解决什么问题:Rust 面向安全系统工程,C 面向 ABI 和极底层,Go 常见于云原生和平台服务,Python 用于 AI、脚本与胶水,TypeScript 用于前端和工具链,Java / C# 用于企业与业务系统,Zig 和 Mojo 则提供了值得关注的新方向。纵向上,则需要积累 C++ 复杂工程的能力。成熟的 C++ 开发者并不是到处推行 C++,而是能判断何时使用它、何时选择别的工具。

未来不是取代,而是重新分工

这场讨论不必归结为 “Rust 会不会取代 C++”。Rust 会在新系统工程中扩大采用,尤其会影响安全敏感的新项目;C++ 仍会服务于复杂高性能、底层处理、历史兼容和长期演化的大型工程;C 继续留在 ABI、裸机、系统边界和平台胶水等位置。业务、AI、前端、移动和脚本,也会由更贴合场景的语言承担。

语言并不沿着一条直线更替,而是在新的需求里调整位置。Rust 改变的是新项目的起点,C++ 保留的是复杂工程的纵深,C 守住的是系统边界。对开发者而言,理解这些边界,比站在某一门语言一边更重要;工具各有来处,也各有去处。

这不是语言战争的结束。

这只是软件工业开始更成熟地分配工具。

这何尝不是一件好事?


  1. What high-performance language to learn? ↩︎

  2. Bjarne Stroustrup Quotes ↩︎