你认为 C++ 最不应该存在的特性是什么?

如果你问大多数长期写 C++ 的人(尤其是用现代 C++ 的开发者),“C++ 最不应该存在的特性是什么?”,答案其实高度分散,但经常被反复点名的几个“罪魁祸首”集中在下面这几类(按被吐槽频率从高到低排序,2024–2025 社区共识视角):

Top 候选名单(社区最常提的“应该删掉/重做”的特性)

  1. C 风格数组 + 指针衰退(array-to-pointer decay) + 裸指针泛滥
    几乎是压倒性票数第一的“原罪”。
  • 为什么最该死:C++ 从 C 继承了“数组名退化为指针”的规则,导致 int a[10]; func(a); 瞬间丢失大小信息,埋下无数越界、内存安全隐患。
  • 现代 C++ 明明有 std::spanstd::arraystd::vectorstd::string_view,但语言层面仍然允许/鼓励裸指针 + 衰退,导致新手/老代码继续写不安全代码。
  • 很多人直言:“如果 C++ 一开始就把数组当成第一类对象(带边界检查),安全性起码提升一个数量级。”
  1. 隐式转换地狱(尤其是单参数构造函数 + 转换运算符)
  • bool operator bool()operator int()MyString(const char*) 这些东西导致的意外转换、歧义、重载解析爆炸。
  • C++11 加了 explicit 但默认还是允许,历史包袱太大。
  • Herb Sutter 等人在安全 profile 里都想把大部分隐式转换干掉。
  1. 多重继承 + 虚继承(virtual inheritance)
  • 菱形继承问题、虚基类指针偏移、内存布局不可预测、调试地狱。
  • 现代 C++ 几乎没人敢用多继承实现(都用接口 + 组合),但语言还保留着完整的机制,增加理解成本和编译器复杂度。
  1. C 风格字符串(char* + strcpy / strlen / sprintf 家族)
  • 缓冲区溢出之源,安全漏洞温床。
  • C++ 提供了 std::string 几十年了,但标准库和 C API 还在到处用 const char*,强制大家写 strlenstrcpy_s 等防御代码。
  1. 头文件 + 重复包含 + 前向声明地狱
  • 没有 modules 之前(C++20 Modules 还是半残),头文件管理是痛苦之最。
  • 即使 C++20/23/26 Modules 来了,兼容旧代码的代价巨大,实际使用率低。
  1. 未定义行为(UB)密度过高
  • 严格别名违规、signed overflow、null 指针解引用、越界、use-after-free 等 UB 太多,而且编译器可以随便“假设不发生”然后生成核弹级优化。
  • 这不是单个特性,而是整个语言哲学的问题,但很多人觉得“默认允许 UB”是最大的设计失误。

如果只能选一个“最不应该存在”的,我个人投给:

数组名到指针的隐式衰退(array-to-pointer decay) + 裸指针作为默认参数/返回类型被允许

理由:

  • 它直接导致了 C++ 前 30 年 70%+ 的内存安全 bug
  • 现代替代方案(span / array / vector / ranges)已经非常成熟
  • 保留这个规则纯粹是为了兼容 1972 年的 C,而这个兼容性代价现在已经远超收益
  • Rust 直接把这个设计砍掉,证明了可以砍,而且砍了之后世界更美好

Bjarne Stroustrup 本人怎么看?

他公开说过几次“后悔”或“如果重来”的点(从访谈/论文中):

  • 没有在早期就强制更强的类型安全
  • 模板语法太复杂(concepts 晚了十几年)
  • 允许太多的隐式行为和兼容 C 的代价

但他也反复强调:“没有哪个主要特性是应该完全删除的”,因为它们都有历史价值和使用场景。

结论(2026 年视角)

C++ 最不应该存在的特性其实不是某个单一功能,而是“为了兼容 C 而保留的大量危险默认行为”这个整体设计决策。

如果能时光倒流,大多数现代 C++ 开发者最想改的可能是:

“让 C++ 从一开始就默认更安全,而不是把安全当成 opt-in。”

你自己最讨厌 C++ 的哪个特性?是上面这些,还是别的更小众的雷(比如 union、goto、volatile、exception specifications 等)?

文章已创建 4138

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部