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

The Cherno C++ Course(个人抄录与注解笔记)(ch1. How C++ Works? )

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

The Cherno C++ Course(个人抄录与注解笔记)(ch1. How C++ Works? )

The better C++ Course for primers by the Cherno(个人抄录与注解笔记)

第一章 How C++ Works?


项目:D:Dev:CppSeriesHello World

文章目录
  • The better C++ Course for primers by the Cherno(个人抄录与注解笔记)
  • 前言
  • 一、How C++ Works?
    • (1)Welcome to C++.
    • (2)How C++ Works?
      • (2.1)C++总体概述
      • (2.2)本节例子
      • (2.3)How the C++ Compiler Works?
        • (2.3.1)基本概念
        • (2.3.2)本节例子
      • (2.4)How the C++ linkers Works?
        • (2.4.1)基本概念
        • (2.4.2)本节例子
  • 抄录总结


前言

以下是笔者关于学习The Cherno C++ Course的个人抄录和注解笔记。本文旨在抄录Cherno课程中所涉及的重要和根本知识,并依据个人所掌握的代码理解程度,添加注释说明。Cherno的讲解除了告诉你如何写好,写快C++代码的同时,他还告诉你–当我们在编写C++代码时,编译器背后到底发生了什么。


学而时习之,不亦说乎?

一、How C++ Works?
(1)Welcome to C++.
  1. C++的使用目标对象:当你需要编写高性能代码时(如:编写大型的游戏项目时),那么C++是挺好的选择。当你需要编写一般性能代码时(如:编写工具类的程序),那么C#或者Java都是挺好的选择。(注:使用C++编写的代码其效率不一定比虚拟机语言(如:C#或者Java)更好。例如:当你同样在编写垃圾代码时,虚拟机语言一般对你所写的代码进行优化,但是C++不会。)
  2. 如果你在学习过程中,善用收索引擎(如:Google,Baidu,BIng)去解决你在学习课程中不理解的地方,同时,如果你对学习C++充满热情,并且真心愿意学习C++,你绝对没有问题的。
  3. 本课程将讨论如何使用C++库,如何避免C++编程中出现的常见错误,C++自身是如何工作的,如何正确使用指针和内存,如何正确使用模板,如何使用宏为多个平台进行编程,*如何自己编写数据结果,并同时让我们所写的 数据结构比库函数更好用,如何使用编译器内联函数来介绍底层优化,如何使用汇编语言(比如写Map和SSE)等等。
(2)How C++ Works?
(2.1)C++总体概述

图1-2-1 C++运行工作的流程图1

使用C++编写程序的简要步骤如下: 2

  1. 编写源代码:当你使用文本编辑器编写文本内容,并将其保存到文件中,这个文件就是程序的源代码。通常,我们将源代码的后缀拓展名设置为.cpp。
  2. 编译源代码:这意味着运行一个程序,要求编译器将源代码(如.cpp文件)翻译为主机(如:使用windows64位系统的电脑)使用的内部语言——机器语言。包含了翻译后的程序的文件,就是程序的目标代码(object code)(在windows系统下,目标代码的后缀格式为.obj)。
  3. 链接目标代码和其他代码,并生产可执行文件:通常,在我们编写C++程序时,都会使用C++标准库(library)。而在C++标准库当中,包含一些列计算机函数的目标代码,这些计算机函数可以帮助我们解决基本的编写任务。同时,链接是指,将目标代码(如:。obj文件)和其他代码一同组合起来,生成最终可执行行的二进制文件(.exe文件)(即,一般生活中,被大众称呼为应用软件。)

(2.2)本节例子

代码如下:

#include 

int main()
{
	std::cout << "Hello World!" << std::endl;
	std::cin.get();
}

注解:

  • 预处理指令:#include 被称为预处理指令(任何以#开头的,都是预处理指令)。并且,当编译器接收到一个源文件时,它所处理的第一件事为,预处理你所有的预处理指令(当计算机在处理#include 这样的预处理指令时,该预处理指令发生在真正的编译之前
    )。
  • "iostream": 在预处理#include 时,iostream文件当中的所有内容都会被黏贴到目前这个main.cpp文件。这里,我们之所以include一个iostream,是因为我们需要函数cout的声明。cout函数使我们能够打印东西到控制台(console)。
  • "main":main函数是我们程序的入口点(entry point)(即,当计算机运行我们的程序时,计算机会从main函数里的代码开始执行)。一般地,计算机会一行一行地执行我们地程序。但,有一些东西可以改变或者打破计算机的执行顺序。如:控制流语句(control flow statements)或者调用其他函数。 所以,本节程序第一个被执行的语句时std::cout << "Hello World!" << std::endl;然后是std::cin.get();。
  • “返回值”:对于熟悉函数的同学,你们可能会注意到,main函数的返回类型其实是整型(int)。然而此处我们并没有返回值,这是因为main函数是个例外,你不需要从主函数返回任何类型的值,如果你不返回任何值,main函数会返回0,请记住,这只使用于main函数。
  • std::cout << "Hello World!" << std::endl;这一语句,对于初学C++同学来说,可能看起来非常奇怪,但其实写成这样是非常不幸的,因为你第一次看它的时候确实看不出来意思。首先,这些向左的带角的括号<<,看起来有点像左位移符号(bit shift),其实是被重载的符号,你得把它看作一个函数。但实际上,运算符就是函数。 所以,我们在这边做的就是,我们把"Hello World!"字符串传入cout中,而cout帮助我们把它打印在控制台上。然后,我们传入一个endl(end line)。endl会告诉我们的控制台前进到另一行。
  • cin.get();在这种情况下,其实就是等待我们输入回车键,然后才会接着执行下一行代码。(一般地,最后使用cin.get();语句,可以使控制台不立即关闭。)当然,我们底下一行什么也没有,所以我们的程序会在cin.get(); 这一行暂停,知道我们按下回车键。最后,当我们在这一行按下回车键时,main函数会返回0,说明我们的程序运行成功了。
(2.3)How the C++ Compiler Works?
(2.3.1)基本概念
  1. 问题引出:在开始学习C++是如何编译源代码时,让我们退后一步,想象一下大的蓝图是什么,C++编译器到底负责什么。
  2. 分析:我们使用文本编辑器编写关于C++的文本内容,就是文本(text)而已。我们需要某种方法将文本(text)转化成应用,从而在计算机运行。从text到可执行二进制文件(.exe),基本有两个主要操作发生者,一个是Compiler,另一个是linker。 本小节回答Compiler。C++编译器要做的工作就是把text转变为中继格式Object Files,然后Object Files会传入linker,linker会进行linking工作。简言之,当我们在讨论Compiler编译产出这些Object Files时,其实Compiler还进行其他几件工作。以下为Compiler进行的具体工作。
  3. 预处理阶段:首先,Compiler会预处理(pre-process)我们编写的代码,也就是所有的预处理指令(如:#include )会在此时被评估。
  4. 标记和解析阶段:其次,Compiler在进行预处理操作之后,它会进入标记(tokenizing)和解析(parsing)阶段。该阶段把我们所编写的C++文本(text),处理成Compiler能懂和处理的语言,即抽象语法树(abstract syntax tree)。 所以,Compiler把我们编写的代码文本(text)转化成常数数据(constant data)或者转化成指令(instruction)。当Compiler创建了一颗抽象语法树后,就可以产生代码了,该代码才是真正CPU可以执行的机器码。
  5. 总结:
    图1-2-2 Compiler工作的流程图。

当Compiler生成抽象语法树之后,我们也会得到一些其他数据,比如某个地方存储着我们所有的常数变量(constant variavles)。以上就是Compiler的基本工作内容,不是非常复杂。当然你的代码越来越复杂,它也越来越复杂。


(2.3.2)本节例子

代码如下:
main.cpp:

#include 

void log(const char* message);

int main()
{
	log("Hello World!");
	std::cin.get();
}

log.cpp:

#include 
void log(const char* message)
{
	std::cout << message << std::endl;
}
  1. 结果:如果我们进入output目录debug下,你可以看到它生成了一个.exe。

    而我们回到项目目录下,你可以看到它生成了main.obj,log.obj。

    综上所述,Compiler给每个.cpp,也就是每个translation unity(编译单元),生成了.obj。本质上,你得意识到C++根本不在乎文件。文件这种东西在C++中不存在。 For example,在Java,你的类(class)名必须跟文件名相同,而你的文件夹结构也得跟package一样。之所以如此,是因为Java(虚拟机语言)需要某些文件存在;而C++完全不是这回事。C++没有文件这种东西。在C++中,文件只是用来个Compiler提供源码的某种方法。 你只需要告诉Compiler文件类型和编译器如何处理它。 例如,我可以新建一个.cherno文件让Compiler去编译,完全没有问题。
    只要我告诉Compiler这是个C++文件,请按C++编译。你最好记住,在C++中,文件不代表任何东西,请记住,这非常重要。 (接下来Cherno还有一段十分钟的例子解析,并通过汇编语言,从底层展示编译器如何进行预处理,以及我们该如何从预处理角度优化我们编写的代码,由于笔者笔力有限,如果阅读到此处,笔者建议读者最好再观看Cherno关于How the C++ Compiler Works的解析。)
  2. 总结:Compiler(这里指代C++编译器)根据我们提供的源代码文件(source file),生成目标文件(Object File)。目标文件(Object File)是由机器码构成的二进制文件。

(2.4)How the C++ linkers Works?
(2.4.1)基本概念
  1. 问题引出:So what is linking? What does the C++ linkers actually do?
  2. 分析:linking是编译源代码后的下一个执行阶段。一旦我们编译了文件,我们接下来需要一个链接(linking)的过程。linking的主要工作是找到每个符号和函数的位置,并将它们链接在一起。又由上一小节有,每个文件被编译成一个独立的.obj文件作为translation unity(编译单元)。实际上,这些编译单元(translation unity)没法沟通。如果,我们决定将程序写在多个C++文件的话,我们需要一种方法将这些文件链接到一个程序。 以上就是linker的主要目的。即使你没有外部文件中的函数,比如说,你已经将整个程序写在一个文件里了,应用程序仍然需要知道entry point(入口点)(即,main函数)在哪里。

(2.4.2)本节例子

代码如下:
math.cpp:

#include 

void log(const char* message)
{
	std::cout << message << std::endl;
}

int Multiply(int a, int b) 
{
	log("multiply");
	return a * b;
}

  • 分析:在此处,我们有两个函数log和multiply。multiply函数实际上调用了log函数,打印出multiply这个单词到控制台,然后返回a*b,该函数非常的简单。然而,这并不是一个实际的应用。因为,显然它不包含main函数。
    你要意识到的第一件事情是,代码运行前有两个阶段——One is Compiling, the other is linking。以下是区分Compiling和linking的方法。

  • 区分Compiling和linking的方法:如果你在VS下按下了Ctrl+F7,或者你按下了编译按钮,只有Compling会发生,而linking则完全不会发生。
    然而,如果你build了你的项目,或者你按下了F5键,它会先Compling,然后再linking。

  • 对上述代码按下Crtl+F7时:你会发现一切都Ok,因为Compiling成功了。
    它产生了相应的math.obj文件,即(Object File),一切似乎都很好。然而,如果右击我的项目,并按下build,你会发现你实际上得到了一个linking Error:入口点必须被定义。

抄录总结
  • 本节简要介绍了How C++ Works?
  • 关于How the C++ Compiler Works? How the C++ linkers Works?的具体细节,还请观看Cherno的视频讲解。
  • 其中如何区分Compiling Error和linkers Error是Cherno所讲述的重点内容,这对于初学者而言,是重要的间接经验。若果你有幸阅读到这里,请务必回看How the C++ linkers Works?这部分视频。
  • 在下一章节,我们将关注C++当中如何更好地使用变量参数。

  1. C++ Primer Plus(第6版 中文版 图1.3 编程步骤) ↩︎

  2. C++ Primer Plus(第6版 中文版 段落1.4 程序创建的技巧) ↩︎

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

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

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