zoukankan      html  css  js  c++  java
  • C++的前世今生

    C++发展史

    C++是什么

    C++ 是一门高级语言,是一种编译型的语言,需要先把源代码先编译成机器语言的可执行程序,然后再执行可执行程序。
    C++世界的“四大天王”
    01

    C++发展史

    "读史使人明智"

    从B到C

      1967年,著名的计算机科学家丹尼斯·里奇(Dennis Ritchie)进入美国AT&T的贝尔实验室工作。一开始,里奇和他的同事肯·汤普森(Ken Thompson)开始研究DEC PDP-7这种早期计算机,但是他们发现在这个机器上写程序很困难,只能使用繁琐的汇编语言编程。所谓的汇编语言(Assembly Language),是一种比较接近计算机底层的低级程序设计语言。在汇编语言中,它用助记符(MOV、PUSH、POP等)代替机器语言的操作码,用地址符号或者标号代替机器语言的地址码。在执行的时候,用汇编语言编写的程序并不能被计算机直接识别和执行,我们还需要通过一个叫汇编程序的工具将汇编语言重新翻译成机器语言,然后交由计算机执行。虽然,汇编语言借助助记符和地址符号在一定程度上降低了编写程序的难度,但是因为它接近计算机底层,因而它所编写出来的程序依然难以阅读和理解,程序的开发效率非常低下。
      为了解决这个难题,汤普森设计了一种高级程序语言来代替汇编语言,并将其命名为B语言。但是由于B语言本身设计的缺陷,使得汤普森在内存的限制面前一筹莫展。到了1973年,里奇对B语言进行了改良,从而赋予了这门新语言强有力的系统控制能力,同时,新语言也做到了简洁而高效。里奇把它命名为C语言,意为B语言的下一代程序设计语言。
      C语言来自B语言,那么B语言是不是来自A语言呢?B语言之前并不存在A语言,之所以取名为B语言,是作者为了纪念他的妻子,他妻子名字的第一个字母是B。
      嗯,程序员中也有情圣啊!
      1978年,里奇和另一位著名的计算机科学家布朗•克尼汉(Brian Kernighan)一起出版了著名的《The C Programming Language》一书,C语言随后逐渐成为世界上应用最广泛的高级程序设计语言,这个版本的C语言也被称为K&R C。1989年,C语言被ANSI(American National Standards Institute,美国国家标准学会,一个由公司、政府和其他成员组成的志愿组织。这个组织负责协商与标准有关的活动,并审议美国国家标准。)标准化(ANSI X3.159—1989)。在K&R C发布后,又不断有人为C语言添加新特性,但C语言的标准在一段相当长的时间内都保持不变,直到20世纪90年代,标准才被更新,这就是ISO 9899:1999(1999年发布)。这个版本就是通常提及的C99。ANSI于2000年3月采用了这个新标准。

    从C到C++

      语言的发展是一个逐步递进的过程。1979年4月,同样是来自贝尔实验室的本贾尼·斯特劳斯特卢普(Bjarne Stroustrup)博士与同事接受了一项工作——尝试分析UNIX的内核。但当时没有合适的工具能够有效地完成这个任务,很难将其内核模块化,所以斯大叔(不是斯达舒哦)的工作进展很慢。同年10月,斯大叔设计了一个预处理程序,称之为“Cpre”。 所谓预处理程序,就是在源程序文件被最终编译之前,对其进行预先处理的程序。Cpre为C语言加上了类似Simula语言的类机制(类机制,一种抽象和封装的机制。它将描述一个事物的数据抽象成类的属性,而将对这些数据的操作抽象成类的方法,然后将属性和方法封装成类。在稍后的第6章中我们将重点介绍这个概念)。在这个过程中,斯大叔萌生了创建一门新语言的想法。贝尔实验室对这个想法很感兴趣,就让他组织一个开发小组,专门进行研究。
      当时这门新语言并不是叫C++,而是叫C with class,它只是C语言的一个有效扩充,后来才更名为C++。当时C语言已经在所有程序设计语言中居于老大的地位,要想发展一种新的语言,最强大的竞争对手就是C语言了。C++ 当时面临两个挑战:第一,C++ 要在运行时间、代码紧凑性和数据紧凑性方面与C语言相媲美;第二,C++ 要尽量避免在语言应用领域的限制。在这种情况下,最简单的方法就是继承C语言的一些特性,让C++ 语言具备C语言的各种优点。同时,斯大叔为了突破C语言的种种局限,还借鉴了其他程序设计语言的优点,实践了编程界由来已久的“拿来主义”。例如:C++ 从Simula拿来了类的概念;从Algol68拿来了操作符重载、引用以及在任何地方声明变量的能力;从BCPL拿来了“//”注释;从Ada拿来了模板、名字空间;从Ada、Clu和ML拿来了异常处理等。通过这一系列的拿来动作,C++ 具备了多种程序设计语言的优秀基因,既系出名门,又博采众家之长,从而完成了从C到C++ 的进化。
      其后,C++ 又经历了长期的发展,随着标准模板库(Standard Template Library,STL)的出现、泛型编程的发展,C++ 在2000年左右出现了其发展史上的一个高峰,而到了2011年,C++ 的最新标准C++ 11正式发布。这个新标准在C++ 的易用性和性能上作了大量改进,增加了线程库等现代软件开发所需要的内容,这也为C++ 的发展注入了新的动力。
      很多朋友都是从C语言转入到C++ 语言的学习的,大家拥有了C语言的基础,同时又因为C语言和C++ 语言之间天然的血缘关系,这使得大家可以对C++ 语言轻松上手,以前的关于C语言的知识和编程经验在C++ 语言中也继续有效。但是,C语言和C++ 语言毕竟是两门不同的编程语言,它们虽然有一定的血缘关系,但是两者之间还是有本质的不同,这就是C++ 比C多出来的两个“+”号。如果说其中一个“+”号代表了C++ 比C语言多出来的体现面向对象思想的类机制,那么另外一个“+”号则代表了C++ 全新添加的标准模板库,正是这两个“+”号将两者区分开来。所以,如果我们是一个有C语言经验的程序员来学习C++ 语言,既需要复用自己以前的关于C语言的知识和经验,同时也应该更新观念,将学习和理解的重点放在面向对象思想的类机制和标准模板库这两个方面,这样才能学习到C++ 语言的精髓。
      C++大事如下:

    • 1983年8月,C++首次投入使用,开天辟地。
    • 1983年12月,Rick Mascitti建议将C with class更名为CPlusPlus,亦即C++。C++ 从此名正言顺。同年,C++吸收了很多新的特性,其中包括虚函数、函数名和操作符重载、常数、用户可控制的自由空间储存区、改良的类型检查及新的双斜线“//”单行注释风格。
    • 1985年2月,C++ Release 1.0发布。
    • 1985年10月,斯特劳斯特卢普博士完成了经典巨著《The C++ Programming Language》的第一版。
    • 1989年,C++ Release 2.0发布。它引入了多重继承、抽象类、静态成员函数及成员访问保护等新特性。C++中面向对象的思想更加成熟。
    • 1990年3月,第一次ANSI X3J16技术会议在美国新泽西州召开。
    • 1990年7月,C++加入模板。
    • 1990年11月,C++加入异常处理。
    • 1991年6月,《The C++ Programming Language》第二版完成。
    • 1991年6月,第一次ISO WG21会议在瑞典召开。
    • 1994年8月,ANSI/ISO委员会草案登记。
    • 1997年7月,《The C++ Programming Language》第三版完成。
    • 1998年10月,ISO标准通过表决被接受。
    • 1998年11月,ISO标准得到批准。同年,C++ 11标准公开,它是当时计划中的C++ 的新标准,将取代现行的C++标准ISO/IEC 14882。
    • 2003年,在官方公布1998标准的5年之后,C++ 标准委员会处理缺陷报告,并于2003年发布了一个C++ 标准的修正版本,称为C++ 03。新的标准包含了核心语言的新功能,同时扩展了C++ 标准程序库,合并了大部分的C++ Technical Report 1程序库。
    • 2005年,公布一份名为Library Technical Report 1(简称TR1)的技术报告。虽然它不属于官方标准,但它所提出的几个扩展建议有望成为新C++ 标准的一部分。目前,几乎所有流行的C++ 编译器都已经支持TR1。
    • 2008年10月,C++11的最新报告N2800公开。
    • 2011年8月,C++ 11(先前被称作C++ 0x)获得ISO/IEC一致通过;同年9月新的C++ 标准C++ 11正式出版,C++ 从此进入一个新的时代。
    • 2017 C++ 17
    • 2020 C++ 2a(又叫C++ 20)

    C++编译历史

    • CFront。由C++ 之父Bjarne在1982~1983年夏完成,不被认为是真正意义上的C++编译器。
    • Turbo C/C++。DOS时代的启蒙先驱,上古神器。
    • 1990年5月,Borland发布了Borland C++,一代传奇宝蓝的作品,Turbo C/C++ 的进化版,可惜掩盖在自家王牌Delphi和外敌Visual C++的光芒之下,远没有这两者的历史地位高。
    • 1992年2月,DEC发布了他们独立开发的C++编译器。
    • 1992年3月,Microsoft发布了VC++。6.0版是一代经典,至今仍老而不死,死而不僵,僵而不化,最新版是2015,
    • gcc。GNU C编译器,1987年由Richard Stallman发布的,原本只能处理C程序,后扩展成可处理C++ 等程序。2013年03月22日,GCC 4.8.0发布,进一步加强了对已C++ 11的支持。2014年04月22日,gcc发布了4.9.0版本,提供了对C11标准的Generic Selection语法特性的支持以及对多线程方面特性的支持。后缀.c的源文件,gcc把它当做c程序,后缀为.cpp,gcc把它当做c++ 程序。
    • g++。GNU C++ 编译器,把.c和.cpp的文件都当做c++ 程序。
    • LLVM。最初由美国UIUC大学的Chris Lattner博士主持开展,2006年Chris Lattner加盟Apple Inc.并致力于LLVM在Apple开发体系中的应用,Apple也是LLVM计划的主要资助者(最初Apple选择的是GCC,后来GCC对Apple的支持不好,不符合苹果的高效、模块化等特点,苹果找了协议更放松的开源替代品)。LLVM是Low Level Virtual Machine的简称,LLVM优化做的更好,可以直接把指令优化成高效的CPU指令。
    • clang。clang只支持C, C++和objective-C三种C家族语言,2007年开始开发,目的是因为gcc系统庞大而笨重,与IDE的配合度差,加上许可证方面的要求,Apple无法使用LLVM继续改进代码质量。2009年时,已经完全用于生产环境。

    clang:

    1. 快。
    2. 内存占用小。
    3. 诊断信息可读性强。
    4. GCC兼容性。
    5. 基于库额模块化设计。
    6. 现在(2019.12.30)已经完全使用了clang。

    GCC:

    1. 支持JAVA/ADA/Fortran
    2. GCC更流行,广泛使用,支持完备。
    3. GCC基于C,不需要C++编译器即可编译。

    C++编译运行的过程

      从源代码到生成一个可执行文件的过程,最好的说法是build(中文翻译的话,有叫生成,有叫编译链接,也有叫构建)

    预处理(preprocessing)

    预处理头文件#include

    注意:

    • <> 代表从系统目录下开始搜索,然后再搜索PATH环境变量所列出的目录,不搜索当前目录
    • "" 表示先从当前目录搜索,然后是系统目录和PATH环境变量所列出的目录下搜索。

    预处理条件编译指令(#ifdef...#endif)

    没啥可说的,主要目的在我看来是选择和避免重复。

    预处理宏(#define)

    将宏定义的变量替换成你自定义的内容。

    #define MY_NAME "Alex"
    cout << "Hello" << MY_NAME << endl;
    相当于
    cout << "Hello" << "Alex" << endl;
    
    gcc -E main.c -o main.i
    // -E的目的是让gcc在预处理结束后停止编译
    

    编译(compiling)

    将预处理阶段的.ii文件编译成.s文件。

    gcc -S main.i -o main.s
    // -S 的作用是编译后结束,编译生成了汇编文件
    //这个过程gcc会检查代码的规范性,是否有语法错误等
    //检查无误后,gcc把代码翻译成汇编语言
    

    汇编阶段(assembly code)

    将编译阶段的.s文件汇编成机器码.o文件,.a是多个.o文件的集合(或者windows的.obj文件,.lib是多个.obj的集合)

    链接(linking)

    把一堆对象文件和库创建成一个单独的可执行文件(如windows下的静态可执行文件.exe或者动态可执行文件.dll),分为动态链接和静态链接:

    1. 静态链接
        将所在地的静态链接库中拷贝到最终的可执行程序中,这样便于最终的移植。
      Unix下无扩展名,Windows下为.exe。
    2. 动态链接
      可执行文件中存在由链接程序记录下共享对象的名字以及少量的登记信息,库文件被放在称作是动态链接库或者共享对象的某个目标文件中。可执行文件被执行时,动态链接库的全部内容被映射到运行时相应进程的虚地址空间,动态链接程序将根据可执行程序中记录的信息找到相应的函数代码。
      Linux下为.so, Windows下为.dll。
      整个过程如下:


    C++终端运行步骤

    直接生成可执行文件

    clang++ main.cpp -o main
    ./main
    //即可运行main,此时同目录下只有可执行文件main。
    

    预编译(.cpp->.ii)

    clang++ -E main.cpp -o main.ii
    

    编译(.ii->.s)

    clang++ -S main.ii -o main.s
    

    汇编(.s->.o)

    clang++ -c main.s -o main.o
    

    链接(.o->可执行文件)

    clang++ main.o -o main
    

    多文件编译

    clang++ -c main1.cpp -o main1.o
    clang++ -c main2.cpp -o main2.o
    //然后链接
    clang++ main1.o main2.o -o main
    ./main
    

    保存编译过程中所有生成的文件

    clang++ -save-temps main.cpp -o main
    //会多生成一个.bc文件,具体的含义看上一节
    

    默认C++中库的位置

    /Library/Developer/CommandLineTools/usr/include/c++/v1/
    
  • 相关阅读:
    January 25th, 2018 Week 04th Thursday
    January 24th, 2018 Week 04th Wednesday
    January 23rd, 2018 Week 04th Tuesday
    January 22nd, 2018 Week 04th Monday
    January 21st, 2018 Week 3rd Sunday
    January 20th, 2018 Week 3rd Saturday
    January 19th, 2018 Week 3rd Friday
    January 18th, 2018 Week 03rd Thursday
    January 17th, 2018 Week 03rd Wednesday
    January 16th, 2018 Week 03rd Tuesday
  • 原文地址:https://www.cnblogs.com/wangzi199/p/13382646.html
Copyright © 2011-2022 走看看