采访 C++ 创造者 Bjarne Stroustrup

介绍

我们与 C++ 的设计者和原始实现者 Bjarne Stroustrup 进行了一次精彩的交谈。他还是 The C++ Programming Language(第四版)、A Tour of C++(第二版)、Programming: Principles and Practice Using C++(第二版)以及许多流行的学术出版物的作者。

享受下面的完整采访!

面试

Evrone:您创建了一种最高效、最快的编程语言。毫无疑问,这改变了我们的世界。作为一个人,你在工作的过程中是否发生了变化?

Bjarne:有趣的问题!没有一个我想太多。我想答案必须区分保持不变的属性和发生巨大变化的属性。

我对包括历史和哲学在内的广泛问题的兴趣从很早开始就一直保持不变,我认为这对 C++ 的发展具有重要意义。我在 1994 年的 D&E 中这么说过。同样,我希望建立更多的东西,而不是深入挖掘学术追求,这使我的工作带有工程偏见。我看重性能、低成本和可靠性。再加上对反馈、进化进步和对现实世界问题的理解的重视,塑造了 C++。

多年来,我的工作稳步增长的一个方面是教育。当我试图解释我的想法时,我意识到你不能只是建造一些东西,你必须教人们很好地使用它。这一直是 C++ 的问题。通常,我的信息会被那些有着更简单愿景和愿意提出更大主张的人淹没。“我们教老师的速度不够快”是我在 1980 年代和 1990 年代的常见抱怨,因此 C++ 的教学方式经常是我认为可怕的。难怪有些人对 C++ 有非常负面的看法!

如果我知道我一生中大部分时间都在说和写英语,我可能会在我的英语(外语)课上更加关注。我的旅行让我对各种各样的问题以及为解决这些问题必须面对的问题范围有了很多见解。许多最困难的问题与组织、管理和教育有关。在那方面,我阅读更广泛的主题比我的技术教育更有帮助。我了解到,良好的语言设计需要高度的谦逊。我们不明白的东西太多了,世界不断变化,我们的问题不断变化,我们也在变化。

Evrone:商业环境要求在实施新功能时遵守严格的最后期限。开发人员如何在代码质量和开发速度之间保持平衡?

Bjarne:这非常依赖于管理结构和技术文化。我个人的意见——主要是在贝尔实验室开发的——理想的情况是你雇佣最好的人,而且数量足够多,这样你就不必让他们在下一个截止日期前全部工作。一些关键人物必须为未来做计划,进行实验,并构建下一个重要系统的第一个版本,也许是之后的下一个版本。我看到一个好的组织构建了稳定的产品流,其中大部分将是已经部署的产品的进化变化,需要维护和升级。显然,这与削减成本和/或明年推出革命性系统的普遍想法不符。

Evrone:现在有一种普遍的看法,即使用现代框架比应用数学知识更重要。你能给年轻的程序员一些关于这方面的建议吗?

Bjarne:花在数学上的时间永远不会浪费,嗯,很少会浪费。数学是训练我们大脑的最佳方法之一,尤其是与计算相结合时,我们的错误很快就会变得明显。数学教我们要准确,不要相信过于简单或错误的想法。

有些领域数学是必不可少的,例如科学计算、某些形式的图形和许多金融软件,但对大多数人来说,数学的关键领域是概率和统计。你的代码够快吗?它会扩展吗?可能发生的事件及其影响是什么?

当然,许多应用程序不需要数学。但是,如果您构建基础设施或大规模部署应用程序,容量和能源成本就会进入画面,而数学上的幼稚可能会造成伤害。

Evrone:强大的 C++ 元编程系统有时会被试图尽可能从运行时转移到编译时的开发人员滥用。从您的角度来看,这是一种可行的方法吗?

Bjarne:每一个新的和强大的特性或技术都会被过度使用和误用。我看不出有什么办法。我们的热情总是随我们而去,所以最终我们必须学会更好地使用我们的工具并退后一点。好消息是过度使用教会了我们很多关于弱点的知识,以便我们可以弥补它们。例如,模板元编程非常有用,以至于许多理性的人愿意忽略它的丑陋和骇人听闻的错误消息。然后,我们学到了足够的东西来补偿编译器时评估的函数(constexpr 和 consteval)和概念,从而大大简化了人们编写的大部分内容。

Evrone:随着来自 DeepMind 的 AlphaCode 神经网络的到来,媒体上越来越多的声明表明这种神经网络将很快取代程序员。你认为这有真正的先决条件吗?

Bjarne:我真的不知道。我怀疑人工智能会取代我最关心的编程类型的程序员。严重的可靠性和接近最佳的性能不太适合标准化和平均化。当我听说 AI 不是我的优势之一时,我提醒自己 TensorFlow 和类似的库都是 C++,所以这意味着我已经尽了自己的一份力——无论好坏。

Evrone:有时,作为开发人员,我们无法为手头的编程任务找到合适的解决方案。你有没有遇到过这样的情况,你能分享一些关于如何处理它们的建议吗?

比亚恩:当然!没有人试图做一些新奇或有意义的事情,不会花费数小时、数天或更长时间陷入困境并感到可怕和沮丧。

你总是试图从逻辑上看问题来理解它。测量,如果有任何东西可以测量以获得反馈。仔细想想你想要做什么:也许你没有这样做,或者你提出的要求不合理。偶尔休息一下,想想别的事情。如果可以,我会去跑步。然后,当我放松时,一些有用的想法经常会在我脑海中浮现。

Evrone:有一个(臭名昭著的)笑话,任何架构问题都可以通过引入一个新的抽象层来解决。除了抽象层太多的问题。我们看到的很多 C++ 代码都有大量的抽象。语言作者关于如何保持抽象计数的任何建议?

Bjarne:这就是David Wheeler 的“计算第一定律”。我很感激你记得下半场——很多人忘记了这一点,但这是必不可少的。David Wheeler 是我的论文导师。他是一个很棒的人,我从他身上学到了很多。

那个“笑话”反映了现实,今天可能比大卫制造的时候更多。人们一直将真正的工作隐藏在涉及间接的多个级别的接口后面。这可能会在大小和/或运行时间上花费一两个数量级。许多现代 C++ 的存在是为了让人们拥有体面的接口,编译器可以将这些接口折叠成简单的机器代码,而无需冗余间接。

Evrone:在过去的十年中,我们看到许多语法糖被添加到主流语言中。您如何看待这种臃肿语法为有经验的开发人员提供更好的工具的趋势?

Bjarne: “臃肿的语法”很好,只要它简化了程序员的生活。我倾向于将其称为“让简单的任务变得简单”。我认为关键思想是让程序员能够直接在代码中表达基本思想。例如,用 C 风格的循环来表达容器上的简单循环没有任何优点或好处。最好使用 range-for 或算法。在大多数情况下,这些直接表达了意图。将循环变量的详细摆弄留给不寻常的情况,例如访问容器的每个第二个元素。更直接的想法表达更容易编写,更容易阅读,更容易维护,并且通常更易于优化,您需要运行得更快。

我不认为“应该只有一种表达方式”是一个充分的理想。如果你这样做,有些事情会变得很难表达,而有些事情只能说太多才能表达出来。此外,多年来和几十年的变化是需要的,这自然会导致语言的变化。在这些方面,编程语言与自然语言并没有什么不同。

Evrone:很多人认为你是他们的导师。您能否分享您的愿景——例如,在公司/团队内部,一个好的导师应该具备哪些品质?

Bjarne:愿意倾听并认真理解问题。然后,在提供建议时要保持一定程度的谦虚——通常,我们的理解是不完整的。也就是说,一个好的导师必须给出具体的建议,而不仅仅是一般的含糊不清的废话。如果有人用一个严肃的问题向你致敬,那么它应该得到一个严肃的答案,以帮助提问者继续前进。提供建议很难。

好问题会教你很多东西。它们是进步的主要来源。一个好的导师会从学生身上学到很多东西。

Evrone:您能否破坏任何您认为值得添加到未来 C++ 版本中的即将发生的语言更改?

Bjarne:首先,社区必须习惯 C++20 的新的、强​​大的和简化的特性。C++20 是对 C++11 的改进。在这里,我只提两个语言特性。还有更多,当然还有标准库组件。

  • 模块:最后,我们可以说import Mod通过 获得对接口exported的访问权限,仅此module Mod而已。#including与泄漏实现细节和宏的标头相比,这提供了更好的代码卫生。模块的编译速度也可以大大加快。例如,我编译一个简单的使用比即使拥有所有标准库和不到 10% 的import std速度快十倍。目前处于试验阶段,但已被投票纳入 C++23。#import<iostream>std<iostream>Module std
  • 概念:在 C++20 之前,所有模板都是不受约束的;也就是说,他们没有定义人们和工具可以查看的接口来确定模板对其参数的要求。例如,template<typename Iter>对于需要迭代器类型的模板。现在我们可以定义这样的需求,称为concepts,并使用它们:template<random_access_iterator Iter>. 这种受约束的模板参数一直是理想的;我只是不知道如何在不限制灵活性或增加运行时开销的情况下实现这个想法。现在我们可以立即检查模板的使用情况,我们可以在出错时得到大大改进的错误消息,我们可以重载函数模板,甚至可以在某些地方提高性能。

您可以在网上找到更详细的信息;例如,查找协程、范围、日历、时区、格式、跨度和编译器时间向量和字符串。C++20 功能已在主要编译器中提供。

现在我可以回到你的问题:未来的版本呢?大流行推迟了很多事情。我们中的许多人都希望看到一些为 C++23 完成的重要项目,但对于我的最爱来说,这并没有发生。在这里,我只提三个:

  • 静态反射:我们需要一种机制在编译时根据程序中的类型生成代码。这将为我们提供运行时反射的几乎灵活性,而无需时间或空间成本。例如,为一组固定类型生成优化优化的 Jason 阅读器应该非常简单。在这方面已经做了大量工作。
  • 模式匹配:基于表达式如何匹配一组类型或值替代项来选择操作的能力是在许多函数式编程语言中表达替代操作的最方便的方法之一。我们可以对 C++ 做同样的事情,并在此过程中使过时的 switch 语句变得多余。我们有一个非常完整的设计和一个实验性的实现,所以我对 C++26 抱有希望。
  • 并发模型:多年来,我们一直在研究并发的通用模型,但我们不断发现明显不适合的用例,因此我们不得不推迟。我对 C++26 抱有希望。请记住,使编程变得方便、安全和高效的并不是单独的功能。我们需要一个密集的特征网络,在类型系统中组合工作。此外,我们无法破坏现有的数十亿行 C++:数十年来的兼容性和稳定性是非常重要的特性。