【C++】001--C++入门(1)

一、C++发展历史

在接下来的介绍中,我们主要学习C++98和C++11,最终还会有C++14以及C++17的拓展。

二、C++参考文档

https://legacy.cplusplus.com/reference/

https://zh.cppreference.com/w/cpp

https://en.cppreference.com/w/

说明:第一个链接不是C++官方文档,标准也只更新到C++11,但是以头文件形式呈现,内容比较易看好懂。后两个链接分别是C++官方文档的中文版和英文版,信息很全,更新到了最新的C++标准,但是相比第一个不那么易看;几个文档各有优势,我们结合着使用。

三、C++的重要性

3.1编程语言排行榜

TIOBE排行榜是根据互联网上有经验的程序员、课程和第三方厂商的数量,并使用搜索引擎(如Google、Bing、Yahoo!)以及Wikipedia、Amazon、YouTube和Baidu(百度)统计出排名数据,只是反映某个编程语言的热门程度,并不能说明一门编程语言好不好,或者一门语言所编写的代码数量多少。

3.2 C++在工作领域中的应用

C++的应用领域非常广泛,涵盖服务器端、游戏(引擎)、机器学习引擎、音视频处理、嵌入式软件、电信设备、金融应用、基础库、操作系统、编译器、基础架构、基础工具以及硬件交互等多个方面。

(1)**大型系统软件开发。**如编译器、数据库、操作系统、浏览器等等。

(2)**音视频处理。**常见的音视频开源库和方案有FFmpeg、WebRTC、Mediasoup、ijkplayer,音视频开发最主要的技术栈就是C++。

(3)**PC客户端开发。**一般是开发Windows上的桌面软件,比如WPS之类的,技术栈的话一般是C++和QT,QT是一个跨平台的C++图形用户界面(Grphical User Interface,GUI)程序。

(4)**服务端开发。**各种大型应用网络连接的高并发后台服务。这块Java也比较多,C++主要用于一些对性能要求比较高的地方。如:游戏服务、流媒体服务、量化高频交易服务等。

(5)**游戏引擎开发。**很多游戏引擎都是使用C++开发的,游戏开发要掌握C++基础和数据结构,学习图形学知识,掌握游戏引擎和框架,了解引擎实现,引擎源代码可以学习UE4、Cocosd-x等开源引擎实现。

(6)**嵌入式开发。**嵌入式把具有计算能力的主控板嵌入到机器装置或电子装置内部,通过软件能够控制这些装置。比如:智能手环、摄像头、扫地机器人、智能音箱、门禁系统、车载系统等等,粗略一点,嵌入式开发主要分为嵌入式应用和嵌入式驱动开发。(本质上是做设备上的程序开发,近几年也比较火,比如智能家居、扫地机器人等等)。

(7)**机器学习引擎。**机器学习底层的很多算法都是用C++实现的,上层用python封装起来。如果你只想准备数据训练模型,那么学会Python基本上就够了,如果你想做机器学习系统的开发,那么需要学会C++。

(8)**测试开发/测试。**每个公司研发团队,有研发就有测试,测试主要分为测试开发和功能测试,测试开发一般是使用一些测试工具(selenium、Jmeter等),设计测试用例,然后写一些脚本进行自动化测试,性能测试等,有些还需要自行开发一些测试用具。功能测试主要是根据产品的功能,设计测试用例,然后手动的方式进行测试。

四、C++学习建议和书籍推荐

4.1 C++学习难度

首先在这里告诉大家C++是一个相对难学难精的语言,相比其他一些语言,学习难度要高一些要陡峭一些,这里有历史包袱问题,也有语言本身设计和发展历史问题。

4.2 C++学习建议

(1)建议把我文章里的所有样例都要练习一遍,理解对应的知识。

(2)建议定期复习学过的知识点,多多看博客来回忆学习内容。

(3)学习书籍推荐:

①C++ Primer:主要讲解语法,经典的语法书籍,前后中期都可以看,前期如果自学看可能会有点晦涩难懂,能看懂多少是多少,就当预习,学了C++后,中后期可以作为语法字典,非常好用。

②STL源码解析:主要从底层实现的角度结合STL源码,庖丁解牛式剖析STL的实现,是侯捷老师的经典之作。可以很好的帮助我们学习别人用语法是如何实现出高效简洁的数据结构和算法代码,如何使用泛型封装等。让我们不再坐井观天,闭门造车,本书在学习中后期可以看。

③Effcitive C++:本书也是侯捷老师翻译的,本书有的一句评价:把C++程序员分为看过此书和没看过此书的。本书主要讲了55个如何正确高效使用C++的条款,建议中后期可以看一遍,工作1-2年后再看一遍,相信会有不一样的收获。

五、 C++的第一个程序

C++兼容C语言绝大多数的语法,所以C语言实现的hello world依旧可以运行,C++中需要把定义文件代码后缀改为.cpp,vs编译器看到的是.cpp就会调用C++编译器编译。其他平台也有相关的C++编译器,比如Linux下是g++。

cpp 复制代码
#include <studio.h>
int main()
{
printf("hello world\n");
return 0;
}

当然C++也有自己的一套输入输出,严格说C++版本的hello world是这样写的:

cpp 复制代码
#include <iostream>
using namespace std;
int main()
{
cout<<"hello world"<<endl;
return 0;
}

六、命名空间

6.1 namespace的价值

在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。

C语言项目类似下面程序这样的命名冲突是普遍存在的问题,C++引入namespacce就是为了更好的解决这样的问题。

cpp 复制代码
//命名冲突
#include <stdio.h>
#include <stdlib.h>
int rand=10;

int main()
{
//编译报错:error C2365:"rand":重定义;以前的定义是"函数"
printf("%d\n",rand);
return 0;
}

6.2 namespace的定义

(1)定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{ }中即为命名空间的成员。命名空间中可以定义变量/函数/类型等。

(2)namespace本质是定义出一个域,这个域跟全局域各自独立,不同的域可以定义同名变量,所以下面的rand不存在冲突了。

(3)C++中域有**函数局部域,全局域,命名空间域,类域;**域影响的是编译时语法查找一个变量/函数/类型出处(声明或定义)的逻辑,所有有了域隔离,名字冲突就解决了。局部域和全局域除了会影响编译查找逻辑,还会影响变量的生命周期,命名空间域和类域不影响变量生命周期。

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

namespace bit{
//命名空间中可以定义变量/函数/类型
int rand=10;

int Add(int left,int right)
{
  return left+right;
}

struct Node
{
  struct Node* next;
  int val;
};

}

int a=1;

int main()
{
  //编译器语法查找确认,默认规则先局部查找->全局查找->没有找到就报错未声明的标识符
  int a=0;
  printf("%d\n",a);
  //域作用限定符
  printf("%d\n",::a);//左边没写默认是全局作用域
  printf("%p\n",rand);
  //编译器语法查找确认,指定作用域,就直接去找这个域查找->没有找到就报错未声明的标识符
  printf("%d\n",bit::rand);
  printf("%p\n",Add);
  printf("%d\n",bit::Add(1,2));
  struct bit::Node node;  //注意这里的语法,注意bit的位置
  return 0;
}

(4)namespace只能定义在全局 ,当然它还可以嵌套 定义。命名空间域中定义的变量依旧是全局变量

cpp 复制代码
//命名空间的嵌套使用

 namespace bit
{
//小李
  namespace xl
  {
    int rand=1;
    int Add(int left,int right)
    {
      return (left+right)*10;
    }
  }
//小王
  namespace xw
  {
    int rand=2;
    int Add(int left,int right)
    {
     return (left+right)*10;
    }
  }
}
int main()
{
printf("%d\n",bit::xl::rand);
printf("%d\n",bit::xw::rand);

return 0;
}

(5)项目工程中多文件中定义的同名namespace会认为是一个namespace,不会冲突。

(6)C++标准库都放在一个叫std(standard)的命名空间中。

6.3 命名空间的使用

编译查找一个变量的声明/定义时,默认只会在局部或者全局查找,不会到命名空间里面去查找。所以下面程序会编译报错。所以我们要使用命名空间中定义的函数/变量,有三种方式:

(1)指定命名空间访问,项目中推荐这种方式。(每个都要去指定)

(2)using将命名空间中某个成员展开,项目中经常访问的不存在冲突的成员,推荐这种方式。(折中方式:部分全部展开)

cpp 复制代码
//部分展开
using std::cout;
using std::endl;  //也就是把这个指令暴露到全局

(3)展开命名空间中全部成员,项目不推荐,冲突风险很大,日常小练习程序为了方便推荐使用。因为如果定义一个和库中变量名完全相同的变量,就会产生冲突。(一把全展开)

cpp 复制代码
using namespace std;//相当于把这个命名空间中的东西暴露到全局,本质上是查找时会在局部查找,全局查找,还会多一步在这个命名空间中查找

七、C++输入&输出

(1)<iostream>是Input Output Stream的缩写,是标准的输入、输出流库,定义了标准的输入、输出对象。

(2)std::cin是istream类的对象,它主要面向窄字符 的标准输入流。(本质上就是把任何类型都转换成字符串,也就是char串输入)

(3)std::cout是ostream类的对象,它主要面向窄字符的标准输出流。(本质上是把任何类型转换成字符串输出)

(4)std::endl是操纵符,底层实现是一个函数,流插入输出时,相当于插入一个换行字符加刷新缓冲区

(5)<<是流插入运算符 ,>>是流提取运算符。(C语言还用这两个运算符做位运算左移/右移)。

(6)使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动指定格式,C++的输入输出可以自动识别变量类型(本质是通过函数重载实现的,这个以后会说到),其实最重要的是C++的流能更好的支持自定义类型对象的输入输出。

cpp 复制代码
#include <iostream>
 int main()
{
int i=100;
i<<5;
double d=1.1;
//任何变量,都转换成字符串,插入到流中
//自动识别类型
std::cout<<i<<'\n'<<"\n";
std::cout<<"hello world"<<std::endl;
std::cout<<i<<" "<<d;
return 0;
}

(7)IO流涉及类和对象,运算符重载、继承等很多面向对象的知识,这些知识我们还没有提到,所以我们这里只能简单的认识一下C++IO流的用法,后面我们会有专门的一个章节来细节IO流库。

(8)cout/cin/endl等都属于C++标准库,C++标准库都放在一个叫std的命名空间中,所以要通过命名空间的使用方法去用它们。

(9)一般日常练习中我们可以使用using namespace std,实际项目开发中不建议using namespace std。

(10)这里我们没有包含<stdio.h>,也可以使用printf和scanf,在包含<iostream>间接包含了。vs系列编译器是这样的,其他编译器可能会报错。

那以后输入输出为什么不用printf和scanf呢?因为这二者只支持简单的数据类型,不支持复杂的数据类型。在以后的学习中,类是复杂类型,IO流支持复杂类型输入输出。


好,这就是我们今天要阐述的内容,简单总结一下,C++本质上就是要解决C语言不足的一些问题:例如命名空间是要解决名字冲突的问题,IO流是要解决复杂类型输入输出问题。

觉得有帮助的朋友们可以一键三连喔~互三必回!后续内容将更加精彩!

相关推荐
hetao17338371 小时前
2026-09-01~09-04 hetao1733837 的刷题记录
c++·算法
传奇开心果编程1 小时前
【Rust入门知识点学与练】第10课:Option 和 Result(错误处理入门)
开发语言·学习·rust
leonkay1 小时前
C# 锁机制——【2】深入原理
开发语言·后端·spring·c#·个人开发
坐吃山猪2 小时前
【多线程】CompletableFuture使用
java·开发语言·多线程
CHPCWWHSU2 小时前
DeepSeek-Harness-Qt将浏览器端Agent装入桌面应用
开发语言·qt
前端 贾公子2 小时前
第10章:RAG(2)
开发语言·python
爱学堂IT分享2 小时前
图灵Java互联网架构师六期
java·开发语言
传奇开心果编程3 小时前
【Rust入门知识点学与练】第3课:String 与 &str 的区别
开发语言·学习·rust
秋名RG3 小时前
Java 核心特性一览
java·开发语言