栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++ 基础与深度分析 Chapter1 C++基础

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++ 基础与深度分析 Chapter1 C++基础

文章目录
  • 什么是C++
    • 与底层硬件紧密结合
    • 对象生命周期的精准控制
    • Zero-Overhead Abstrction
  • C++的开发环境与相关工具
  • C++的编译/链接模型

什么是C++


C++是C语言的一种扩展,更关注性能。与底层硬件紧密结合,这就是自动驾驶和机器人为什么要会C++。
C++引入了大量的特性,除了面向对象,C++还是面向过程的方式,或者是泛型编程(近年来关注开始增加)。
C++还有函数重载,异常处理,引用等等。

与底层硬件紧密结合


大端和小端是硬件的概念。

不同计算机,可能结果是完全不一样的,所以输出和底层硬件紧密结合的。但是java就不会。
如果两台机器,一台发数据是大端法,另一台接数据是小端法,这就是不合理的。java就没关系。所以c++是更关注性能。java更关注易用性。
易用性和高性能基本来说是一个balance的关系。有些语言是牺牲性能,c++就更关注性能,但是易用性就差一些,不如java和python。

对象生命周期的精准控制

c# 使用完,不用管。易用性更好,但是性能会损耗。引用一个垃圾回收机制,额外的线程去维护。
c++从构造,使用,销毁,都是程序员精确的控制的。这同样是易用性和性能的平衡问题。

左边是c++,右边是c#。
在c++,处理异常,使用try(构造的对象,如果有异常,对象就销毁了),发现异常就抛出,然后catch即可。
c#,如果有try抛出异常,那么try里面的对象,没有及时的被销毁。所以就需要通过finally进行销毁。
上面就是对生命周期的精确控制不同,导致语言书写的不同。
生命周期的精准控制,好处就是提升性能。c++避免了垃圾回收的机制的额外消耗。

Zero-Overhead Abstrction


虚函数的引用是在程序运行的时候,这会对程序的运行造成负面的影响。c++关注性能,如果我的类中没有虚函数,我就不需要付出额外的成本。但是c#,所有的类和对象,都是继承object的,所有的都是虚函数,和python一样。即使这个类,没有用到派生,都要付出虚函数的成本。但是c++不需要这样。

func2运行效率比较高。
c#都是在堆上构造的,很少在栈上构造,需要间接引用,付出额外的成本。

从c++角度讲,这个函数包含循环,我们是用了c++的特性,但是右边编译器,并没有付出运行期的成本。为什么?c++包含了编译,连接等等。不需要付出运行期的成本,是因为我们付出了编译器的成本。
这里用了c++20的一个特性,consteval,编译只运行了一次,我们可以容忍这一次的编译,运行期的时候,直接拿结果过来即可。


标准在不断的演进,工业界的实现,并不能跟上发展的速度。这就是理想照进现实的情况。

严肃说法:我使用了什么c++标准,什么工具进行开发。
这门课主要讨论c++17以及之前的特性。额外少量c++20的一些特性。
编译环境,我们会尝试不同的gcc和clang为主,在vs也是可以进行编译的。
我们要关注性能和标准。性能是c++是c语言继承过来,对底层更精准把控。如果写出来的性能,和java和python差不多,还不如不写。如果用c++开发,就一定要关注性能。c++的标准,也是不断的引进,进行查漏补缺。所以要遵守标准。标准,很大程度上是解决移植的问题。

C++的开发环境与相关工具


集成开发,就是一个壳,便于组织。
valgrind:程序有没有内存泄漏,Linux常用的工具。
cpp reference:c++的百科全书,c++的标准,遇到问题去这里查。
Compiler exploer:写出来程序,在网站可以直接编译代码。还可以选择编译器。只能贴一个文件。只是看一段代码的工作状态。
c++ insights:将代码进行解释,比如一些新的语法,它到底做的什么,翻译成老的。

C++的编译/链接模型


简单的加工模型,加工耗时较长,即使是少量的修改,也需要全部重新加工。

分块处理,编译比较耗费资源,c++翻译成机器码,c++源文件和机器码并不是一对一的关系。翻译就比较困难,机器需要理解源文件,机器不需要很大的输入,分成了小块,每次处理一个小块。
链接虽然输入比较多,但是由于工作内容比较简单,处理起来也不是很慢。这是一个扬长避短的模型,有助于模型的修改和升级。源文件1有错误,只修改源文件1,2-n不需要任何修改,编译源文件1,再将1和2-n进行链接。

由分块处理,衍生出的概念:

  • 定义/声明:在不同的源文件里,可能使用了相同的变量,比如说i,这时就要区分出变量的定义和声明,在某个地方引入了变量的定义,比如在源文件1,定义了x。在源文件2-n,可能都使用了同样的定义x,2-n只是声明我要使用这个变量x,但不是在我这里定义的。最后在链接的时候,会在源文件1里,有x的定义。

  • 头文件/源文件:构造一个头文件,包含了需要的所有声明,不需要一个个去声明。然后源文件2-n引用这个头文件。当编译器解析到这个源文件引用了一个头文件,它会去展开头文件,进行编译。提升代码的书写效率。源文件引用头文件,头文件最早是引用声明,但是不止包含声明,可以包含定义。

  • 翻译单元:翻译单元包含了一个源文件,一个源文件引用了很多头文件,把这些头文件的内容展开,放到源文件中,同时源文件忽略里面的预处理语句。一个源文件 + 直接/间接 头文件 - 预处理语句,所以编译器处理的不是源文件,而是一个翻译单元。

  • 一处定义原则:可执行程序设计到的所有翻译单元里,对于一个东西,只能有一处定义。

    预处理:源文件转为翻译单元,将源文件的头文件进行展开,防止头文件被循环展开。



    头文件被无穷层的嵌套了。
    用#ifdef解决。



    这个就没问题。


    循环展开就被仿制了。这个解决方案有不足之处,在header1和header2,但是如果宏重名了,就无法解决了。在新的c++解决,pragma once记数一次。




编译优化也有缺点,如果不优化,可以debug,但是优化了,就不利于debug。debug编译和release编译。

开发用debug,开发完用release进行编译。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/893236.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号