C++ 为什么难?

御宅暴君
御宅暴君 @otakutyrant
A Tour of C++ - 评论

A Tour of C++ 在二〇二二年十月终于出第三版了,已更新到 C++20 并有若干 C++23 内容。内容简洁,是给有编程经验的读者看的。通过这书我彻底理解了 object,variable,initialization,value 等的定义,也明白了 declaration,definition 和 initialization 之间的微妙关系,真是大道至简。

虽然这书很容易让读者变得对 C++ 胸有成竹,包括我。但我后来又意外发现,一旦语法细节叠加起来,就是编程难度上的指数爆炸,A Tour of C++ 就刻意不提这现象,虽然本来就无能为力且也没必要。Bjarne Stroustrup 说过他给自己对 C++ 的理解打分的话,七十分。

比如 int *aint a[10] 一看就知道分别声明了 int 指针和 int 数组,但 int *a[10] 又声明了什么呢?A Tour of C++ 就没有讲,它只提及了 *[]& 是 declaration operators。但 "declaration operators" 这个看似正式,但并不是 C++ 标准的术语(大概),而且 Declaration 语法本身就非常复杂,我都没想到声明时原来还有那么多东西可以塞进去,鬼知道怎么匹配它们之间的关系,显然理解难度等于 N 次方。C 业界甚至曾流传过错误的民间说法:The Spiral Rule

当看到 The Spiral Rule 时,我脑补出:斯意佳佳螺旋剑!

知乎上也有人说明了当 move 语义,默认参数,模板等结合起来 C++ 就变得面目可憎

出自 Initialization in C++ is Seriously Bonkers

C++ 为了兼容 C,背上了很多历史包袱,与此又添加了改进这些历史包袱的现代语法。于是现代 C++ 就同时存在两种非正交的新旧语法,比如 NULL vs nullptr,const char * vs std::string,header file vs module,enum vs enum class,union vs std::variant,函数的返回类型声明在前 vs 函数参数后面用箭头声明的返回类型等。C++ 改进还特别慢,以三年为周期单位,搞笑的是 C++20 引入了 module,但还不能直接 import std,要到 C++23 才行。我估计 C++ 到死也没法 deprecate 那些该死的历史包袱了。我看了 LeetCode 上的 C++ solutions,绝大部分写的其实是 C,而不是 C++。

再次,C++ 同时支持多个编程范式:过程式编程,面向对象编程,泛型编程,元编程,函数式编程。再加上标准库编程(我胡诌的,也包括容器,算法等)和系统编程(包括 I/O,文件,网络等操作系统 API)。其中标准库编程产生了 Erase–remove idiom 这个诡异的奇技淫巧。多种编程范式叠加起来,再次爆炸。

最后,我发现 C++ 有太多 implication 了:int a = 1.2,后者会被 implicitly converted;base class 的某函数被声明为 virtual 时,所有 derived functions 也会被 implicitly 声明为 virtual,我在 r/cpp_questions 问了好多问题才 get 这语法;int a 看似一个 declaration,但也可能是 defination,即 initialiazed as zero implicitly;所有 class 的 special function members 应该会 be defined implicitly,除非定义其中一个 member function explicitly 或是 delete 它,于是看到若某人说某 class 没有 constructor,意思其实是没有 define constructor explicitly,或是没有 user-defined constructor(其实和前一子句同一个意思),或是故意声明为 =delete。此外这害得你很容易搞不清楚 declaration,initialization,definiation,implementation,user-defined 之间的关系,因为有些词语是 ambiguous,=delete 是一种 definition 吗,T a = T() 是 assignment,但也是 initialization 吗?上文提到的语法叠加灾难我还可以容忍,但这种 C++ implicit 语法让我出离愤怒!怪不得 Linus 要破口大骂。Crap!

所以,C++ 难。

Written with StackEdit.