C++的最后一道坎|百万年薪的程序员
| 导语 C++ 的起源可以追溯到 40 年前,但它仍然是当今使用最广泛的编程语言之一,C++发明人Bjarne Stroustrup 一开始没想到 C++ 会获得如此大的成功,他说:“C++ 的成功显然令人惊讶。我认为它的成功取决于其最初的设计目标,就是有效的使用硬件,再加上强大的抽象机制,以及它根据来自实际使用情况的反馈进行谨慎的发展”。
C++历史背景
C ++编程语言的历史可以追溯到1979年,当时Bjarne Stroustrup为博士学位论文进行了一些开发。在Stroustrup可以使用的所有单词中,有一种被称为Simula的语言,顾名思义,它可能是一种主要为仿真而设计的语言。Simula 67语言是Stroustrup使用的变体,被认为是支持面向对象编程范例的主要语言。Stroustrup发现这种范例对包装开发很有帮助。但是,Simula语言对于实践和实际使用而言太慢了;
随后不久,Bjarne Stroustrup希望通过支持面向对象范例来增强C。他深入研究了Smalltalk的OO实现,以获取有关实现的想法。但是他不愿意为此放弃性能,因此他开始从事“C with Classes (带有类的C) ”的工作,希望C ++代码运行时应具有与C代码相似(或更好)的性能。
第一个带有类别编译器的C称为Cfront,它是从称为CPre的C编译器派生而来的。它曾经是一个旨在将带有类别代码的C转换为通用C的程序。值得注意的目的是Cfront主要是用C用类编写的,从而创建了一个自举的编译器(可以自行编译的编译器) 。Cfront后来在1993年被放弃,但是Cfront对未来的编译器和Unix操作系统的实现产生了巨大影响。
1983年,语言的名称从“带有类的C”更改为C ++。C语言中的++运算符是用于递增变量的运算符,它使您可以深入了解Stroustrup如何看待该语言。在此期间添加了许多新功能,其中最引人注目的是虚函数,函数重载,带有&符号的引用,const关键字和使用两个正斜杠的单行注释。
1985年,Stroustrup引用了名为“ C ++编程语言”的语言。已出版。同年,C ++被实现为商业产品。该语言尚未正式标准化,因此使该书成为非常重要的参考。该语言在1989年再次进行了更新,以包括受保护的成员和静态成员,以及从多个类的继承.
1990年,发行了《带注释的C ++参考手册》。同年,Borland的Turbo C ++编译器将作为商业产品发布。Turbo C ++添加了许多其他库,这些库会对C ++的开发产生相当大的影响。尽管Turbo C ++的最后一个稳定版本是2006年,但该编译器仍被广泛使用。
1998年,C ++标准委员会发布了第一个C ++ ISO / IEC 14882:1998国际标准,其非正式名称为C ++ 98。据说《带注释的C ++参考手册》对标准的制定产生了很大的影响。还包括标准模板库,该模板库于1979年开始概念开发。2003年,该委员会对1998年标准所报告的多个问题做出了回应,并对其进行了相应的修订。更改的语言称为C ++ 03。
2005年,C ++标准委员会发布了一份技术报告(称为TR1),详细介绍了他们计划添加到最新C ++标准中的各种功能。新标准被非正式地称为C ++ 0x,因为它有望在第一个十年结束之前的某个时间发布。具有讽刺意味的是,新标准要到2011年年中才会发布。直到那时为止,已经发布了几份技术报告,并且一些编译器开始为新功能添加实验性支持。
2011年中,新的C ++标准(称为C ++ 11)完成。Boost库项目对新标准产生了重大影响,其中一些新模块直接来自相应的Boost库。一些新功能包括正则表达式支持,全面的随机化库,新的C ++时间库,原子支持,标准线程库 ,一种新的for循环语法,提供的功能类似于某些其他语言中的foreach循环,auto关键字,新的容器类,对联合和数组初始化列表以及可变参数模板的更好支持。
2014年,C ++ 14(也称为C ++ 1y)作为C++11的一个小扩展发布,主要功能是错误修复和小的改进,国际标准投票程序草案于2014年8月中完成,加强lambda函数,constexpr和类型推导特性;
2017年,发布C++17标准,C++17提供了很多东西。增强了核心语言和库;
2020年,发布C++20标准,推出了很多重量级功能,其中比较重要:
Concepts:概念改变了我们思考和编程模板的方式。它们是模板参数的语义类别。它们使您可以直接在类型系统中表达您的意图。如果出了什么问题,您会收到清晰的错误消息。
Ranges library:新的ranges库使它可以直接在容器上执行算法,用管道符号组成算法,并将其应用于无限数据流。
Coroutines:由于协程,C ++中的异步编程成为主流。协程是协作任务,事件循环,无限数据流或管道的基础。
Modules:模块克服了头文件的限制。他们承诺很多。例如,头文件和源文件的分离变得和预处理器一样过时了。最后,我们有更快的构建时间和更轻松的构建软件包的方法。
Concurrency:
Atomic Smart Pointers,
Joining & Cancellable Threads,
The C++20 Synchronization Library,增强了C++并发编程能力;
总结一下,C++标准演进路线如下图:
从C++发展历史背景来看,C++产生的根本原因有两点:
面向对象编程: Bjarne Stroustrup研究Simula OOP编程思想,觉得这个是应对大型软件开发的绝佳武器,拥有很好的现实抽象能力和代码组织能力;
高性能:Bjarne Stroustrup准备开发一套通信系统,需要编写接近硬件的低级代码,例如内存管理器、进程调度器和设备驱动程序来分离软件组件,由于当时计算机硬件性能限制,对软件性能要求苛刻,广泛使用的C语言有比较接近硬件工作的能力,所以Bjarne Stroustrup基于C语言创造可以面向对象编程的C++语言;
推荐学习:
《An Overview of the C++ Programming Language》Bjarne Stroustrup
《Design and Evolution of C++》Bjarne Stroustrup
怎么才能深刻理解面向对象思想?
面向对象程序设计的雏形,早在1960年的Simula语言中即可发现,当时的程序设计领域正面临着一种危机:在软硬件环境逐渐复杂的情况下,软件如何得到良好的维护?面向对象程序设计在某种程度上通过强调可重复性解决了这一问题。20世纪70年代的Smalltalk语言在面向对象方面堪称经典——以至于30年后的今天依然将这一语言视为面向对象语言的基础。
维基百科:
面向对象程序设计(英语:Object-oriented programming,缩写:OOP)是种具有对象概念的编程典范,同时也是一种程序开发的抽象方针。它可能包含数据、属性、代码与方法。对象则指的是类(class)的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性,对象里的程序可以访问及经常修改对象相关连的数据。在面向对象程序编程里,计算机程序会被设计成彼此相关的对象。
面向对象编程就是通过对象把现实世界映射到计算机模型的一种编程方法,是抽象思维的一种体现。而抽象是计算机科学中最重要的一种思维方式;
面向对象方法的本质就是主张从客观世界固有的事物出发的构造系统,提倡用人类在现实生活中常用的思维方法来认识、理解和描述客观事物,具体实现采用对象为基础,对象是面向对象方法中最基本的概念。对象可以用来表示客观世界中的任何实体,它既可以是具体的物理实体的抽象,也可以是人为的概念,或者是任何有明确边界和意义的东西;
程序的本质是人的意志延伸到计算机的可识别的指令。计算机(CPU)仅能识别 01代码,本身不能解决任何问题(无意识),只能由人编写程序控制计算机解决问题,因此编程的本质就是人“教会”计算机解决问题。
面向对象的编程技术有助于减小这一隔阂、并使这两个空间尽量趋于一致;
抽象思维一直推动着计算机技术不断向前发展,科学技术本身就是现实世界的抽象和演绎:
电路信号->01二进制->指令汇编->高级编程->模块设计->框架设计->单机系统->分布式系统-->云计算
推荐学习:
《深入理解计算机系统》
《编码:隐匿在计算机软硬件背后的语言(美.佩措尔德)》
封装
主要的方法是对象和类:
对象是面向对象方法中最基本的概念。对象可以用来表示客观世界中的任何实体,它既可以是具体的物理实体的抽象,也可以是人为的概念,或者是任何有明确边界和意义的东西;
类是具有共同属性、共同方法的对象的集合,是关于对象的抽象描述,反映属于该对象类型的所有对象的性质,它由一组静态特征(数据)和它可执行的一组操作(方法)组成,一个对象就是类的一个实例;
对象和对象之间隐藏自己内部实现细节,通过标准接口进行通信,这样就可以提高程序内聚,降低耦合,方便系统进行解耦设计,同时也提高了系统稳定性,降低系统风险。
继承
主要的方法通过类的公有继承、保护继承,私有继承,单继承,多继承;结合类成员的三种属性:public、protected 和 private; 来实现共享和限制属性和方法的访问;
继承的优点是:相似的对象可以共享程序代码和数据结构,从而大大减少了程序中的冗余信息,提高软件的可重用性,便于软件迭代;
多态
编译时多态
主要的方法是重载和模板,重载包括运算符重载和函数重载,运算符重载通过重新定义运算符实现函数来实现,底层还是函数重载,函数重载通过参数列表的不同来区分不同的方法,底层是不同的函数签名;
模板是通过参数化类型来区分不同类和函数;
细节请参考:
《C++ Templates: The Complete Guide》
运行时多态
主要方法是重写,子类对父类方法的“重新”实现,底层是通过定义虚函数和构建虚函数表,在虚函数表里面插入RTTI(运行时类型信息)信息,结合继承和动态绑定,程序就可以根据实际类型判断并调用相应的属性和方法。
细节请参考:
《深度搜索c++对象模型》
多态强大的功能允许不修改父类代码和业务逻辑代码,就通过扩展子类来实现功能的扩展。多态使模块在复用的基础上具备了更强的可扩展性;
C ++的设计目标
高效地使用硬件
保持与C语言兼容,C++代码与C代码运行时应具有相似(或更好)的性能;
将内置操作和类型直接映射到硬件,以提供有效的内存使用和有效的低级操作;
零成本的抽象机制
低成本的灵活抽象机制,可为用户定义的类型提供与内置类型相同的符号支持,用途范围和性能;
类,继承,模板,概念,别名等;
任何违反以上两个设计目标之一的建议都可能会遭到拒绝;
C ++的未来目标
更加灵活,支持多种编程范型:
面向过程编程:兼容C语言编程,支持自上而下面向过程编程;
面向对象编程:封装,继承,多态,对象内存模型,构造和析构;
泛型编程:泛型编程是自 STL(标准模板库)纳入到 C++ 标准以后才逐渐流行起来的新范式,核心思想是“一切皆为类型”,或者说是“参数化类型”“类型擦除”,使用模板而不是继承的方式来复用代码,所以运行效率更高,代码也更简洁;
模板元编程:模板元编程是一种高级、复杂的技术,C++模板是图灵完备的,可以在编译期间模拟一个完整的图灵机,也就是说,可以完成任何的计算任务,比如编译期数值计算、类型计算、代码计算(如循环展开),而类型计算和代码计算可以使得代码更加通用,更加易用,性能更好;
函数式编程:核心思想是以函数对象(可以作为入参和返回值),无状态(无副作用),更加强调程序执行的结果而非执行的过程,倡导利用若干简单的执行单元让计算结果不断渐进,逐层推导复杂的运算,C++已经提供了一些基本元素:Lambda表达式,std::function、函数对象。模板元编程等;
更好的类型系统:内置更多类型(通过标准库扩展),更安全类型系统,更好类型泛化编程支持,支持自省,反射等特性;
更好资源的安全性:更好的对象内存模型,更好对象所有权设计(可以学习借鉴Rust),更好异常安全机制;
更好利用硬件:caches,多核(更好支持并发编程),GPUs,FPGA,SIMD等;
看Bjarne Stroustrup专访,关于程序语言设计哲学讨论,更能体会到C++的核心设计思想;
我挑选一些自己觉得比较重要的实践条目,大家可以自行修正补充一下:
尽量使用现代C++(C++11 以上)进行C++编程,开发效率,性能,安全性都有极大提高;
尽量使用智能指针,用RAII模式管理对象生命周期;
理解C++对象的内存模型和布局,方便定位和解决各种C++内存问题;
异常是一个即安全又危险的特性,请谨慎使用;
熟悉常见的设计模式和C++特有的设计范式,帮助自己设计构建更好的系统,对代码进行必要的重构;
代码一定要做单元测试,测试代码尽量覆盖所有的分支(覆盖率尽量高),可以采用GoogleTest单元测试框架;
代码最好用valgrind等工具跑一遍,检查代码有没有内存泄漏和异常;
C语言:
《The C Programming Language》
学习C++,离不开C语言的了解,此书被誉为C语言的圣书,需要反复细读。
手册参考书籍:
《C++标准程序库(C++ Standard Library Tutorial and Reference) 》
《C++编程规范(C++ Coding Standards) 》
用来当手册使用,有需要时候查询一下。
C++初学者入门:
《C++ Primer》
此书为入门经典书籍,初学者一定要经常翻看。
如何更好编写C++程序:
《Exceptional C++》
让你了解C++经验用法,避免踩坑。
C++内存模型:
《深度搜索c++对象模型》
让你理解C++内存布局,对C++各种内存异常问题有帮助。
泛型编程:
《深入浅出STL》
《Beyond the C++ Standard Library(Boost)》
可以学习泛型编程精髓。
modern C++:
《深入理解C++11》
《Effective Modern C++》
C++11版本以后被称为modern C++,代表一个新时代C++诞生,写代码更快,更好,更稳。
高手进阶
模板编程:
《C++ 模板完全指南(C++ Templates: The Complete Guide)》
《C++设计新思维-泛型编程与设计模式之应用(Modern C++ Design ) 》
《C++模板元编程(C++ Template Metaprogramming)》
《Advanced c++ Programming Styles and Idioms 》
如果想看懂标准库STL或者boost库代码,需要了解一些模板编程相关的知识。
设计模式:
《设计模式:可复用面向对象软件的基础》
《Modern C++ Design》
《More C++ Idioms》
《Advanced c++ Programming Styles and Idioms 》
了解一下常用设计模式和C++设计惯用方法,可以更好设计C++系统。
两个经典网站:
http://www.cplusplus.com
https://en.cppreference.com
用来查询标准库API和使用说明,以及标准说明解释