Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 3

# 1.

前言

最初,我设计 C++ 是为了回答这样的一个问题:如何直接操作硬件,同时又支持高效、高级的抽象?C++ 在


1980 年代仅仅是一个基于 C 和 Simula 语言功能的组合,在当时的计算机上作为系统编程的相对简单的解决
方案,经过多年的发展,已经成长为一个远比当年更复杂和有效的工具,应用极其广泛。它保持了如下两方面的
关注:

- **语言构件到硬件设施的直接映射**
- **零开销抽象**

这种组合是 C++ 区别于大多数语言的决定性特征。“零开销”是这样解释的 [Stroustrup 1994]:

- 你不用的东西,你就不需要付出代价(“没有散落在各处的赘肉”)。
- 你使用的东西,你手工写代码也不会更好。

抽象在代码中体现为函数、类、模板、概念和别名。

C++ 是一种活的语言,因此它会不断变化以应对新出现的挑战和演变中的使用风格。2006 年至 2020 年期间


的这些挑战和变化是本文的重点。当然,一门语言本身不会改变;是人们改变了它。所以这也是参与 C++ 演化
的人们的故事,他们识别出面临的挑战,诠释解决方案的局限,组织他们的工作成果,并解决他们之间必然出现
的分歧。当我呈现一种语言或标准库特性时,其背景是 C++ 的一般发展和当时参与者的关切。对于在早期被接
受的许多特性,我们现在从大量的工业使用中获得了后见之明。

C++ 主要是一种工业语言,一种构建系统的工具。对于用户来说,C++ 不仅仅是一种由规范定义的语言;它是由


许多部分组成的工具集的一部分:

- 语言
- 标准库
- 许多的其他库
- 庞大的——常常是旧的——代码库
- 工具(包括其他语言)
- 教学和培训
- 社区支持

只要有可能,只要合适,我就会考虑这些组成部分之间的相互作用。

有一种流传广泛的谬见,就是程序员希望他们的语言是简单的。当你不得不学习一门新的语言、不得不设计一门
编程课程、或是在学术论文中描述一门语言时,追求简单显然是实情。对于这样的用途,让语言干净地体现一些
明确的原则是一个明显的优势,也是理想情况。当开发人员的焦点从学习转移到交付和维护重要的应用程序时,
他们的需求从简单转移到全面的支持、稳定性(兼容性)和熟悉度。人们总是混淆熟悉度和简单,如果可以选择
的话,他们更倾向于熟悉度而不是简单。

看待 C++ 的一种方式是,把它看成几十年来三种相互矛盾的要求的结果:

- **让语言更简单!**
- **立即添加这两个必要特性!!**
- **不要搞砸我的(任何)代码!!!**

我添加了感叹号,因为这些观点的表达常常带着不小的情绪。
我想让简单的事情简单做,并确保复杂的事情并非不可能,也不会没有必要地难。前者对于不是语言律师的开发
者来说是必不可少的;后者对于基础性代码的实现者是必要的。稳定是所有意图持续运行几十年的系统的基本属
性,然而一种活的语言必须适应不断变化的世界。

C++ 有一些总体构想。我阐述了一些(如《C++ 语言的设计和演化》(*The Design and Evolution of


C++*)[Stroustrup 1994]([§2](02.md#2-背景 c-的-19792006))、设计原则([§9.1](09.md#91-
设计原则)),以及 C++ 模型([§11.1](11.md#111-c-模型)))并试图让语言在演化时遵循它们。然而,
C++ 的开发由 ISO 标准委员会控制,它主要关注的是长长的新特性列表,以及对实际细节的关心。这是社区里
最能表达和最有影响力的人所坚持的东西,仅仅基于哲学或理论观点就否认他们的关切和意见的话,恐怕就失之
鲁莽了。

## 1.1 年表

为了给出一个快速的概述,这里有一个粗略的年表。如果你不熟悉 C++,很多术语、构件、库都会晦涩难懂;大
多数在以前的 HOPL 论文 [Stroustrup 1993, 2007] 或本文中有详细解释。

- 1979 年:工作始于“带类的 C”,它变成了 C++;拥有了第一个非研究性的用户;


- 语言:`class`、构造函数/析构函数、`public`/`private`、简单继承、函数参数类型检查
- 库:`task`(协程和仿真支持)、用宏参数化的 `vector`
- 1985 年:C++ 的首次商业发行;TC++PL1 [Stroustrup 1985b]
- 语言:`virtual` 函数、运算符重载、引用、常量
- 库:`complex` 算法,流输入输出
- 1989–91 年:ANSI 和 ISO 标准化开始;TC++PL2 [Stroustrup 1991]
- 语言:抽象类、多重继承、异常、模板
- 库:输入输出流(但没有 `task`)
- 1998 年:C++98、第一个 ISO C++ 标准 [Koenig1998]、TC++PL3 [Stroustrup 1997]
- 语言:`namespace`、具名类型转换[^1]、`bool`、`dynamic_cast`
- 库:STL(容器和算法)、`string`、`bitset`
- 2011 年:C++11 [Becker 2011],TC++PL4 [Stroustrup 2013]
- 语言:内存模型、`auto`、范围 `for`、`constexpr`、lambda 表达式、用户定义字面量……
- 库:`thread` 和锁、`future`、`unique_ptr`、`shared_ptr`、`array`、时间和时钟、随机数、
无序容器(哈希表)……
- 2014 年:C++14 [du Toit 2014]
- 语言:泛型 lambda 表达式、`constexpr` 函数中的局部变量、数字分隔符……
- 库:用户定义字面量……
- 2017 年:C++17 [Smith 2017]
- 语言:结构化绑定、变量模板、模板参数的构造函数推导……
- 库:文件系统、`scoped_lock`、`shared_mutex`(读写锁)、
`any`、`variant`、`optional`、`string_view`、并行算法……
- 2020 年:C++20 [Smith 2020]
- 语言:`concept`、`module`、协程、三路比较、改进对编译期计算的支持……
- 库:概念、范围、日期和时区、`span`、格式、改进的并发和并行支持……

请注意,早年 C++ 的库是很匮乏的。事实上,当时还是存在大量各种各样的库(包括图形用户界面库),但很


少被广泛使用,并且很多库是专有软件。这是在开源开发普及之前的事。这造成了 C++ 社区没有一个重要的共
享基础库。在我的 HOPL2 论文 [Stroustrup 1993] 的回顾中,我认为那是早期 C++ 最糟糕的错误。
任务库 [Stroustrup 1985a,c] 是一个基于协程的库,支持事件驱动的仿真(例如随机数生成),与替代方
案相比是非常高效的,甚至可以运行在很小的计算机上。例如,我在 256KB 的内存中运行了 700 个任务的仿
真。任务库在 C++ 早期非常重要,是贝尔实验室和其他地方许多重要应用的基础。然而,它有点丑陋,并且不
容易移植到 Sun 的 SPARC 体系结构,因此大多数 1989 年以后的实现都不支持它。2020 年,协程才刚刚回
归([§9.3.2](09.md#932-协程))。

总的来说,C++ 的特性不断增多。ISO 委员会也废除了一些特性,对语言进行了稍许清理,但是考虑到 C++ 的


大量使用(数十亿行代码),重要的特性是永远不会被移除的。稳定性也是 C++ 的关键特性。要解决跟语言不
断增长的规模和复杂性相关的问题,办法之一是通过编码指南([§10.6](10.md#106-编码指南))。

## 1.2 概述

这篇论文是按照 ISO 标准发布的大致时间顺序组织的。

- [§1](#1-前言):前言
- [§2](02.md#2-背景 c-的-19792006):背景:C++ 的 1979–2006
- [§3](03.md#3-c-标准委员会):C++ 标准委员会
- [§4](04.md#4-c11 感觉像是门新语言):C++11:感觉像是门新语言
- [§5](05.md#5-c14 完成-c11):C++14:完成 C++11
- [§6](06.md#6-概念):概念
- [§7](07.md#7-错误处理):错误处理
- [§8](08.md#8-c17 大海迷航):C++17:大海迷航
- [§9](09.md#9-c20 方向之争):C++20:方向之争
- [§10](10.md#10-2020-年的-c):2020 年的 C++
- [§11](11.md#11-回顾):回顾

如果一个主题跨越了一段较长的时间,比如“概念”和标准化流程,我会把它放在一个地方,让内容优先于时间
顺序。

这篇论文特别长,真是一篇专题论文了。但是从 2006 年到 2020 年,C++ 经历了两次主要修订:C++11 和


C++20;而论文的早期读者们也都要求获得更多的信息。结果就是论文的页数几乎翻倍。即使以目前的篇幅,读
者也会发现某些重要的主题没有得到充分的展现,如并发和标准库。

[^1]: 译注:即新的、非 C 风格的类型转换

You might also like