1.C++了解(可跳过)
1.1 C++发展历史
C++的起源可以追溯到1979年,当时Bjarne Stroustrup(本贾尼·斯特劳斯特卢普,这个翻译的名字不同的地方可能有差异)在贝尔实验室从事计算机科学和软件工程的研究工作。面对项目中复杂的软件开发任务,特别是模拟和操作系统的开发工作,他感受到了现有语言(如C语言)在表达能力、可维护性和可扩展性方面的不足。
1983年,Bjarne Stroustrup在C语言的基础上添加了面向对象编程的特性,设计出了C++语言的雏形,此时的C++已经有了类、封装、继承等核心概念,为后来的面向对象编程奠定了基础。这⼀年该语言被 正式命名为C++。
在随后的几年中,C++在学术界和⼯业界的应用逐渐增多。⼀些⼤学和研究所开始将C++作为教学和研究的首选语言,而⼀些公司也开始在产品开发中尝试使用C++。这⼀时期,C++的标准库和模板等特性也得到了进⼀步的完善和发展。
C++的标准化工作于1989年开始,并成立了⼀个ANSI和ISO(International Standards Organization)国际标准化组织的联合标准化委员会。1994年标准化委员会提出了第一个标准化草
案。在该草案中,委员会在保持斯特劳斯特卢普最初定义的所有特征的同时,还增加了部分新特征。
在完成C++标准化的第一个草案后不久,STL(Standard Template Library)是惠普实验室开发的一系列软件的统称。它是由Alexander Stepanov、Meng Lee和David R Musser在惠普实验室工作时所开发出来的。在通过了标准化第一个草案之后,联合标准化委员会投票并通过了将STL包含到C++标准中的提议。STL对C++的扩展超出C++的最初定义范围。虽然在标准中增加STL是个很重要的决定,但也因此延缓了C++标准化的进程。
1997年11月14日,联合标准化委员会通过了该标准的最终草案。1998年,C++的ANSI/IS0标准被投入使用。
“C++语言之父”:本贾尼·斯特劳斯特卢普
1.2 C++参考文档
官方:C++ 参考手册 - cppreference.com
1.3 C++在工作中的应用
C++的应⽤领域服务器端、游戏(引擎)、机器学习引擎、音视频处理、嵌入式软件、电信设备、⾦融应用、基础库、操作系统、编译器、基础架构、基础工具、硬件交互等很多方面都有。
1. 大型系统软件开发。如编译器、数据库、操作系统、浏览器等等
2. 音视频处理。常见的音视频开源库和方案有FFmpeg、WebRTC、Mediasoup、ijkplayer,⾳视频开发最主要的技术栈就是C++。
3. PC客户端开发。⼀般是开发Windows上的桌面软件,比如WPS之类的,技术栈的话⼀般是C++和QT,QT 是一个跨平台的 C++图形用户界面(Graphical User Interface,GUI)程序。
4. 服务端开发。各种大型应用网络连接的高并发后台服务。这块Java也比较多,C++主要用于一些对性能要求比较高的地方。如:游戏服务、流媒体服务、量化高频交易服务等
5. 游戏引擎开发。很多游戏引擎就都是使用C++开发的,游戏开发要掌握C++基础和数据结构,学习图形学知识,掌握游戏引擎和框架,了解引擎实现,引擎源代码可以学习UE4、Cocos2d-x等开源引擎实现
6. 嵌入式开发。嵌入式把具有计算能力的主控板嵌入到机器装置或者电子装置的内部,通过软件能够控制这些装置。比如:智能手环、摄像头、扫地机器人、智能音响、门禁系统、车载系统等等,粗略一点,嵌入式开发主要分为嵌入式应用和嵌入式驱动开发。
7. 机器学习引擎。机器学习底层的很多算法都是用C++实现的,上层用python封装起来。如果你只想准备数据训练模型,那么学会Python基本上就够了,如果你想做机器学习系统的开发,那么需要学会C++。
8. 测试开发/测试。每个公司研发团队,有研发就有测试,测试主要分为测试开发和功能测试,测试开发一般是使用一些测试工具(selenium、Jmeter等),设计测试用例,然后写一些脚本进行自动化测试,性能测试等,有些还需要自行开发一些测试用具。功能测试主要是根据产品的功能,设计测试用例,然后手动的方式进行测试。
2.C++启程
2.1 C++的第一个程序
C++兼容C语言绝大多数的语法,所以C语言实现的hello world依旧可以运行,C++中需要把定义问件代码后缀改为.cpp,vs编译器看到是.cpp就会调⽤C++编译器编译,linux下要用g++编译,不再是gcc
// test.cpp
#include<stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
当然C++有一套自己的输入输出,严格说C++版本的hello world应该是这样写的
// test.cpp
// 这⾥的std cout等我们都看不懂,没关系,下⾯我们会依次讲解
#include<iostream>
using namespace std;
int main()
{
cout << "hello world\n" << endl;
return 0;
}
2.2 命名空间的使用
编译查找一个变量的声明/定义时,默认只会在局部或者全局查找,不会到命名空间里面去查找。所以下面程序会编译报错。所以我们要使用命名空间中定义的变量/函数,有三种方式:
- 指定命名空间访问,项目中推荐这种方式。
- using将命名空间中某个成员展开,项目中经常访问的不存在冲突的成员推荐这种方式。
- 展开命名空间中全部成员,项目不推荐,冲突风险很大,日常小练习程序为了方便推荐使用。
#include<stdio.h>
namespace sui
{
int rand = 0;
}
int main()
{
// 编译报错:error C2065: “rand”: 未声明的标识符
printf("%d\n", rand);
return 0;
}
这里会报错( 编译报错:error C2065: “rand”: 未声明的标识符)
我们需要访问这个命名空间要使用“::”操作符
2.2.1 访问命名空间成员
#include<stdio.h>
namespace sui
{
int rand = 0;
}
int main()
{
printf("%d\n", sui::rand);
return 0;
}
2.2.2 展开命名空间
#include<stdio.h>
namespace sui
{
int rand = 0;
}
using namespace sui;
int main()
{
printf("%d\n", rand);
return 0;
}
2.2.3 展开命名空间成员
#include<stdio.h>
namespace sui
{
int rand = 0;
}
using sui::rand;
int main()
{
printf("%d\n", rand);
return 0;
}
2.3 命名空间的存放
命名空间与C语言结构体类似结构,但命名空间中可以定义变量/函数/类型,也可以存放命名空间
namespace sui
{
//变量
int rand = 0;
//函数
int add(int x, int y) {
return x + y;
}
//命名空间
namespace man {
int a = 10;
double f = 10.2;
}
}
大大避免了逻辑上的冲突,看一个实例 :
#include<stdio.h>
#include<stdlib.h>
//全局变量
int rand = 10;
int main() {
//显示状态重定义;以前的定义是“函数”
printf("%d", rand);
//在stdlib.h中,rand为函数,可以在C++参考文献查询
return 0;
}
这里就会报错!!!为了避免这种情况
#include<stdio.h>
#include<stdlib.h>
namespace sui {
int rand = 10;
}
int main() {
printf("%p", rand);
//打印函数地址
printf("%d", sui::rand);
//打印命名空间的rand
return 0;
}
C++的输入与输出
<iostream> 是 Input Output Stream 的缩写,是标准的输入、输出流库,定义了标准的输入、输出对象。
std::cin 是 istream 类的对象,它主要⾯向窄字符narrow characters (of type char))的标准输入流。
std::cout 是 ostream 类的对象,它主要⾯向窄字符的标准输出流。
std::endl 是一个函数,流插入输出时,相当于插入一个换行字符加刷新缓冲区。
<<是流插入运算符,>>是流提取运算符。(C语言还用这两个运算符做位运算左移/右移)
使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动指定格式,C++的输入输出可以自动识别变量类型(本质是通过函数重载实现的,这个以后会讲到),其实最重要的是C++的流能更好的支持自定义类型对象的输入输出。
IO流涉及类和对象,运算符重载、继承等很多面向对象的知识,这些知识我们还没有讲解,所以这里我们只能简单认识⼀下C++ IO流的用法,后面我们会有专门的⼀个章节来细节IO流库。
cout/cin/endl等都属于C++标准库,C++标准库都放在⼀个叫std(standard)的命名空间中,所以要通过命名空间的使用方式去用他们。
⼀般日常练习中我们可以using namespace std,实际项目开发中不建议using namespacestd。
这里我们没有包含<stdio.h>,也可以使用printf和scanf,在包含<iostream>间接包含了。vs系列编译器是这样的,其他编译器可能会报错。
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
//这里是直接展开
//如果没有展开,则std::进行访问
int main()
{
int a = 0;
double b = 0.1;
char c = 'x';
//C++中的输入域输出会自动匹配类型
cout << a << " " << b << " " << c << endl;
std::cout << a << " " << b << " " << c << std::endl;
//C语言则需要手动匹配类型
scanf("%d%lf", &a, &b);
printf("%d %lf\n", a, b);
// 可以⾃动识别变量的类型
cin >> a;
cin >> b >> c;
//endl为换行符等同于"\n"
cout << a << endl;
cout << b << " " << c << endl;
return 0;
}