一基础部分
0.历史
- 1995-1998年,ansi的c++98标准发布
- 2003,c-Primier-plus的版本
- 2011,第二个正式版,有右值引用、自动类型推断,规定stl的统一命名空间,委托构造函数
- 2014,做了些修复
- 2017,inline内联函数(另一个作用:初始化类的静态变量)、
- 2020,线程
1.C++的基础部分
- c的前置知识:面向过程,只有函数和结构体
- 预编译#:引入头文件或宏指令
- 宏指令#define:常用来定义常量
- system():调用系统命令行的命令
- 预编译#:引入头文件或宏指令
- 命名空间:全限定名,c+沿用了。
- 目的:防止多头文件下的函数冲突
- using xx:限定空间,否则要引用空间名::
- 代码块:限定内存区域
- 全局变量:类似于JavaScript,并且存在作用域
- 全局访问:使用指针
- 访问冲突:使用::全限定名
- 全局变量:类似于JavaScript,并且存在作用域
- 枚举:static final的常量
- 使用:::代替.
- 结构体:声明一块自定义类型的内存
- 声明struct xx{}:至少的大小和基础类型
- 使用xx.property:构造一块类似于对象的引用
- 内存:存在栈里。
- std命名空间下的:集合、输入输出、数据结构
- array<int,length>:拥有方法size()、
- static_cast<int>:
- vector<int> xx:接近于java的arraylist用法,可初始化大小和数组,但不用new分配空间
- 新特性:clear()清除数组、push_back()自动扩容相当于java的add()、empty()是否空
- cout和cin:用符号<<进行操作
- hex、oct:等格式化输出数据
- unique_ptr:唯一性的指针,
- 初始化同java:{new int[]{}或类},make_unique<泛型>(值)
- reset():释放内存,清除指针值。
- get():返回他的指针地址给指针。
- release():释放内存,返回原始的指针地址。
- 转移:move()来转移指针指针
- share_ptr:共享指针,但是需要所有都释放
- unique():是否唯一指针
- use_count(): 返回几个使用他的指针
- reset():如果最后一个则释放
- 字符串:是面向对象封装的类型
- 不同点:访问是通过下标[]
- find=charat()
- 万物转字符串:std::to_string()
- 字符串函数:std::stoi()转整数、stoxx直接转某个类型
- wchar_t类型数组:是一个宽字节16字节一个字符——相当于String底层
- Stringstream:以流方式操作字符串
- 对比:十分类似stringbuffer
- 不同点:访问是通过下标[]
- 函数:同主流语言,特别是typescript
- 参数:可令指针为传入和返回参数,同java传入引用类型
- 函数指针:类似于JavaScript的函数表达式设计
- sizeof()是一个编译器识别的常量,只能根据定义推断。
- 重载:同java,但是指针和数组引用是一样的。
- 常量指针:const,只读不允许修改引用值。
- 默认参数:只能放在最后面
- 不定参数:使用宏库<cstdarg>收集指针va_start
- 本质:存在代码区(类似于方法区),栈地址固定。
- 函数2:
- 右值引用:存放在临时空间的没有声明的变量的引用&,例如函数返回值、计算表达式,不能写入的变量
- 作用:避免复制,可以用于函数参数
- 引用参数:尽量加const,这样在接右值或不正确类型时能生成临时变量。
- 指针参数:使用时要一直带着*,这叫解引用
- 返回引用类型:也应该用const,这样能限制直接修改对象的值。注意:他不能返回函数里的临时对象,除非new一份。
- 总体原则:不修改的用const,修改的不加
- 函数模板:相当于是泛型方法
- 在函数上加temlpate<typename t1>,返回类型不确定可以为auto或decltype(auto)
- 本质:当传入参数不同调用的call是不同的函数指针(由编译器来生成)。
- 具体化:不使用模板而是自定义的定义<>
- 右值引用:存放在临时空间的没有声明的变量的引用&,例如函数返回值、计算表达式,不能写入的变量
- decltype():根据括号里的值进行类型推断
- 规则1、2:可以是函数返回值、已定义变量类型
- 规则3:存在表达式左值引用或增加()时,则是创建引用类型。如果是右值或普通变量则是原始类型
- 规则4:不执行括号里的计算值。
- 用法:配合auto使用推导函数的返回值。
- decltype(auto):引用即引用,指针即指针。
- 区别:对于指针的引用创建有不同
- 拖尾函数:强制使用引用auto bigger(int& a,int &b)->int&
- 联合体:union
- 联合体更适合在内存有限的情况下,需要同时保存多个不同类型的变量,但是只能存储其中一个变量的值的情况;
- 很少用
- 内存对齐:要按最大基本类型的大小对齐
- 面向对象
- 构造函数:就是执行函数并分配内存。
- explicit:禁用类型转换,一般用于函数前,则调用时无法隐转
- 构造函数:则此对应类在初始对象时无法直接从 vec.push_back(10); // 错误:无法进行隐式转换
- 只有使用static_cast<int>(t);
- default:就是提高析构和默认构造函数效率的语法糖。
- 运算符重载
- 作用:类似于函数,在成员内默认左边就是类对象,友元函数能操作对象变量。
- 说明:有严格的限制,三种情况:成员函数、全局函数、友元函数
- int operator =()
- 多重继承:
- 虚函数:virtual和override(只是为了让编译器检查是否参数一致)
- 作用:通常使用基类的指针来调用(向上转型)
- 虚类:解决多重继承中的成员重复问题。否则只能用命名空间A::var
- 析构函数:得将析构函数设为虚函数,因为会触发所有析构函数。
- 纯虚函数:如下图,即是
- typeid:类似于typeof+instanceof获取运行时数据类型,但不能用于指针、数组、函数
- 抽象类:就是有virtual的纯虚函数的类
- 友元类:允许另一个类访问自己的私有成员和保护成员的类。
- 类似于定义在外边的内部类A中声明b,则b能使用A,
- 友元函数:能
- 函数调用约定:
- cdecl:能从右往左入栈,支持多参数
- 区别:调用者恢复栈平衡。
2.指针的顶级理解
- 基本构成:地址和大小
- 定义类型:int*指定一个4字节大小的变量的内存开头地址:int* x=&A,定义和使用赋值不一样。
- 使用:存地址取地址运算
- p取址符号&:=&A取得一个命名变量的地址
- p地址变量直接赋值:=0x0001改地址
- *p取变量间接赋值:=6666给指向地址的值赋值
- p指针运算:是按类型加指定大小例如int就是4字节
- 指针:
- 指针本身大小:4字节,表达总共的内存寻址范围:32位4gb
- 意义:大小由定义类型决定,但可操作任一一块地址——使用取址&A
- 定义和使用:定义一般直接给地址值,使用可以取或直接赋值和取或间接赋值
- 指针的括号:
- 数组指针:(*ptr),可以指向数组[5],指向二维数组则长度为其一维的长度[][6]——正经的类型int[]*
- *ptr:指向数组[5]表示是指针数组
- 内存:
- 分配:malloc(字节大小)返回该块内存的指针、calloc(,倍数)指定数量、relloc(2,8)重新指定大小
- new int:分配出一块内存空间在堆里
- 释放:free(指针)——必须清0不能出现野指针
- delete 指针:释放该指针内存,删除一段数组要用 delete[] 指针,删除对象也要delete[]
- 复制:memcpy(目的指针,指针,字节)、memset(地址,值,字节大小)
- 区别:推荐用new、delete[]
- 对于对象的区别:不仅删除,而且会调用构造函数和析构函数。
- 分配:malloc(字节大小)返回该块内存的指针、calloc(,倍数)指定数量、relloc(2,8)重新指定大小
- 继承的内存机制:
- 继承子类对象里面有父类的内容。因为执行了父类构造器。
- 虚函数表:类为单位,继承时改写每个虚函数表中元素的值(函数地址),
- dynamic_cast<目标>:强制动态转换,一般用于父类转子类,即向下转型
- 类的底层机制:
- 虚函数表:以类为单位,所有虚函数的指针在里面,对象new出来后会有一个指针vptr到对象中。
- 总结:跟java差不多,子类的虚表重写方法会覆盖原来虚函数地址,否则不会。
- 类信息:类似于java中的方法区
- 虚函数表:以类为单位,所有虚函数的指针在里面,对象new出来后会有一个指针vptr到对象中。
- 堆栈:
- 引用:就是一个指针,只不过不能手动改变地址。
- 栈管运行方法(main区),堆管数据(手动管理)。
- 函数栈:函数调用会生成调用栈,上层可以访问底层的变量。
3.cpp的编译
- 头文件h:存放函数和全局变量声明的文件
- extend:声明一个外部变量,函数默认是extend,会让编译器从另一处找到代码定义地址。函数名本质上就是一个代码区地址。
- extend "C" xx:定义一个c风格的声明
- 一般全局变量不需要用,局部变量要用
- lib文件:二进制文件
- 使用:在源码里引入头文件,相当于让编译器知道是个引用。
- 编译:添加依赖项,或手动引入二进制#pragma comment(lib,"xx.lib")
- 只能使用一次:#pragma once
- 定义:只定义方法,也可以定义inline和static变量和方法,会直接存到全局区,同名源文件引入后并实现该定义。
- 宏定义:
- 作用:就是定义一些常量、预处理指令
- 预定义宏:程序的常规常量,例如_func_等
- 断言:assert()
- 作用:编译检查某些表达式的bool值,
- 使用:需要<cassert>库,取消:#define nodebug
- extend:声明一个外部变量,函数默认是extend,会让编译器从另一处找到代码定义地址。函数名本质上就是一个代码区地址。
- 源文件:
- 代码区:存放函数的内存,类似于只放函数的堆,只读不能修改(因为没用变量)
- 通信:依靠引入同一个头文件实现。
- 编译器:
- gnu c++:开源,但代码庞大
- clang:使用llvm前端,苹果出品
- mvc++:vs专属
- 链接属于编译后端
- llvm详解:
- IR:负责连接编译
- 表现形式:ll形式——人能看,特征为
- 编译器前端
- 语法提取:
- 语法分析:解析成语法生成树
- 后端:
- IR:负责连接编译
- 项目构建:就是管理依赖、编译、运行配置的工具
- cmake:使用makelist配置,生成ninja或makefile文件
- vs project:
- makefile和ninja:根据特定语法规则进行编译项目
4.windows的接口
5.进阶多线程
6.网络库(cgi)
- winsocket:
7.汇编
- 基础概念:
- []:代表间接寻址
- 寄存器
- eax下:通用的寄存器
- esp、ebp:与函数调用栈有关,ebp是记录函数中断地址
- ecx:用于循环的局部变量。
- 指令:
- lea:专门存地址
- imul:三个参数时可以指定存放地址
- add、sub、inc、dec:加减后放到第一个操作数地址
- 栈结构:栈顶与地址增加方向相反
- call之前:
- 把参数复制压入栈中,
- call时:
- 压入ebp和esp,esp随时指向栈顶
- 压入callee-saved寄存器包括ebx,edi和esi
- 将返回的执行结果保存在eax中
- 将callee-saved寄存器复原
- _stdcall栈平衡:由调用函数来栈平衡ret 8
- call之后:
- ebp用来恢复调用者的基址寄存器值。
- _cdecl栈平衡:由调用者实现栈平衡——esp要向下移动,把多余的参数压栈出掉。
- _fastcall:通过eax和edx传参,堆栈平衡由调用者维护。
- _thiscall:类访问的默认方式
- call之前:
8.dll动态链接库
- 概念:pe格式的二进制文件,应用程序用lib文件(内存地址)链接到dll的函数库
- 对比:类似于jar包,内容是多个类文件,可被动态加载到内存中被引用。
- 区别:dll是进程共享、但class只能线程共享。dll是平台相关常驻内存,class是平台无关动态加载。
- 相似:都能被共享,都能节省内存,都是为了节省代码。
- 开发:编写源码文件—编写同名头文件(需要用_declspec字段暴露)—编译项目生成lib、dll文件
- 使用:导入命名空间(头文件)—引用链接库—使用方法
- 工具:Dumpbin
- 查看导出:
dumpbin -exports xxx.dll
- 查看导入:
dumpbin -imports xxx.exe
- 查看导出:
9.Hook开发
- 基本概念:hook就是修改dll文件内容执行额外代码。内核级别的hook有一些是加密的,但也有很多是开放api的,例如进程拦截等。
- 详情参考这篇文章
- 微软不允许,否则会吊销驱动签名。
- 内存注入:调用api,修改内存数据,需要确定基址
- 缺点:容易被检测到
- 工具:aheadlib
- 功能:根据输入DLL的导出表生成劫持源码。
10.逆向工程
- 游戏外挂
- ce:能搜索进程中的内存数据
- 变化数据:
- 精度确认:
- 汇编调试台:查看内存区域
- x32dbg:
- ce:能搜索进程中的内存数据
- ida:
二.框架部分
1.mfc
2.qt
独立了,请查阅:
3.h.264和ffmpeg
三.图形开发
0.前言
- 图形渲染:底层调用api是openGL等库操作硬件显卡
- 常见的引擎:
- 浏览器:webgl
- 桌面:
- 游戏引擎:unity3d、
1.openGL
2.DirectX
四.项目
1.加密播放器
- 基本库
2.qt的天气预测系统
3.音视频系统开发
- 基本库
- 客户端
- 服务端
4.IM后台
5.远程控制
本文作者为byzhj,转载请注明。