本仓库是面向C/C++技术方向校招求职者、初学者的基础知识总结,包括语言、程序库、数据结构、算法、系统、网络、链接装载库等知识及面试经验、招聘、内推等信息。
const使用
缺点
虚函数内联使用
#include
assert()使用
#defineNDEBUG//加上这行,则assert不可用#include
#pragmapack(push)//保存对齐状态#pragmapack(4)//设定为4字节对齐structtest{charm1;doublem4;intm3;};#pragmapack(pop)//恢复对齐状态位域Bitmode:2;//mode占2位类可以将其(非静态)数据成员定义为位域(bit-field),在一个位域中含有一定数量的二进制位。当一个程序需要向其他程序或硬件设备传递二进制数据时,通常会用到位域。
extern"C"使用
#ifdef__cplusplusextern"C"{#endifvoid*memset(void*,int,size_t);#ifdef__cplusplus}#endifstruct和typedefstructC中//ctypedefstructStudent{intage;}S;等价于
//cstructStudent{intage;};typedefstructStudentS;此时S等价于structStudent,但两个标识符名称空间不相同。
另外还可以定义与structStudent不冲突的voidStudent(){}。
由于编译器定位符号的规则(搜索规则)改变,导致不同于C语言。
一、如果在类标识符空间定义了structStudent{...};,使用Studentme;时,编译器将搜索全局标识符表,Student未找到,则在类标识符内搜索。
即表现为可以使用Student也可以使用structStudent,如下:
//cppstructStudent{intage;};voidf(Studentme);//正确,"struct"关键字可省略二、若定义了与Student同名函数之后,则Student只代表函数,不代表结构体,如下:
typedefstructStudent{intage;}S;voidStudent(){}//正确,定义后"Student"只代表此函数//voidS(){}//错误,符号"S"已经被定义为一个"structStudent"的别名intmain(){Student();structStudentme;//或者"Sme";return0;}C++中struct和class总的来说,struct更适合看成是一个数据结构的实现体,class更适合看成是一个对象的实现体。
联合(union)是一种节省空间的特殊的类,一个union可以有多个数据成员,但是在任意时刻只有一个数据成员可以有值。当某个成员被赋值后其他成员变为未定义状态。联合有如下特点:
union使用
#include explicit使用 Derived(parms):Base(args){}using指示using指示使得某个特定命名空间中所有名字都可见,这样我们就无需再为它们添加任何前缀限定符了。如: usingnamespace_namename;尽量少使用using指示污染命名空间一般说来,使用using命令比使用using编译命令更安全,这是由于它只导入了指定的名称。如果该名称与局部名称发生冲突,编译器将发出指示。using编译命令导入所有的名称,包括可能并不需要的名称。如果与局部名称发生冲突,则局部名称将覆盖名称空间版本,而编译器并不会发出警告。另外,名称空间的开放性意味着名称空间的名称可能分散在多个地方,这使得难以准确知道添加了哪些名称。 using使用 尽量少使用using指示 intx;std::cin>>x;std::cout< usingstd::cin;usingstd::cout;usingstd::endl;intx;cin>>x;cout< decltype(expression)decltype使用 右值引用就是必须绑定到右值(一个临时对象、将要销毁的对象)的引用,一般表示对象的值。 右值引用可实现转移语义(MoveSementics)和精确传递(PerfectForwarding),它的主要目的有两个方面: 好处 用花括号初始化器列表初始化一个对象,其中对应构造函数接受一个std::initializer_list参数. initializer_list使用 面向对象三大特征——封装、继承、多态 把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。关键字:public,protected,private。不写默认为private。 函数重载 classA{public:voiddo(inta);voiddo(inta,intb);};动态多态(运行期期/晚绑定)注意: 动态多态使用 classShape//形状类{public:virtualdoublecalcArea(){...}virtual~Shape();};classCircle:publicShape//圆形类{public:virtualdoublecalcArea();...};classRect:publicShape//矩形类{public:virtualdoublecalcArea();...};intmain(){Shape*shape1=newCircle(4.0);Shape*shape2=newRect(5.0,6.0);shape1->calcArea();//调用圆形类里面的方法shape2->calcArea();//调用矩形类里面的方法deleteshape1;shape1=nullptr;deleteshape2;shape2=nullptr;return0;}虚析构函数虚析构函数是为了解决基类的指针指向派生类对象,并用基类的指针删除派生类对象。 虚析构函数使用 虚继承用于解决多继承条件下的菱形继承问题(浪费存储空间、存在二义性)。 实际上,vbptr指的是虚基类表指针(virtualbasetablepointer),该指针指向了一个虚基类表(virtualtable),虚表中记录了虚基类与本类的偏移地址;通过偏移地址,这样就找到了虚基类成员,而虚继承也不用像普通多继承那样维持着公共基类(虚基类)的两份同样的拷贝,节省了存储空间。 用于分配、释放内存 malloc、free使用 申请内存,确认是否申请成功 char*str=(char*)malloc(100);assert(str!=nullptr);释放内存后指针置空 free(p);p=nullptr;new、deletenew、delete使用 intmain(){T*t=newT();//先内存分配,再构造函数deletet;//先析构函数,再内存释放return0;}定位new定位new(placementnew)允许我们向new传递额外的地址参数,从而在预先指定的内存区域创建对象。 合法,但: 方法:将析构函数设置为私有 原因:C++是静态绑定语言,编译器管理栈上对象的生命周期,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性。若析构函数不可访问,则不能在栈上创建对象。 方法:将new和delete重载为私有 原因:在堆上生成对象,使用new关键词操作,其过程分为两阶段:第一阶段,使用new在堆上寻找可用内存,分配给对象;第二阶段,调用构造函数生成对象。将new操作设置为私有,那么第一阶段就无法完成,就不能够在堆上生成对象。 头文件:#include weak_ptr允许你共享但不拥有某对象,一旦最末一个拥有该对象的智能指针失去了所有权,任何weak_ptr都会自动成空(empty)。因此,在default和copy构造函数之外,weak_ptr只提供“接受一个shared_ptr”的构造函数。 被c++11弃用,原因是缺乏语言特性如“针对构造和赋值”的std::move语义,以及其他瑕疵。 向上转换是一种隐式转换。 bad_cast使用 try{Circle&ref_circle=dynamic_cast 顺序栈数据结构和图片 队列数据结构 typedefstruct{ElemType*elem;intfront;intrear;intmaxSize;}SqQueue;非循环队列非循环队列图片 SqQueue.rear++ 循环队列图片 SqQueue.rear=(SqQueue.rear+1)%SqQueue.maxSize 顺序表数据结构和图片 链式数据结构 typedefstructLNode{ElemTypedata;structLNode*next;}LNode,*LinkList;链队列(LinkQueue)链队列图片 单链表图片 双向链表图片 循环链表图片 哈希函数:H(key):K->D,key∈K 线性探测的哈希表数据结构和图片 函数直接或间接地调用自身 广义表的头尾链表存储表示和图片 扩展线性链表存储表示和图片 二叉树数据结构 typedefstructBiTNode{TElemTypedata;structBiTNode*lchild,*rchild;}BiTNode,*BiTree;顺序存储二叉树顺序存储图片 二叉树链式存储图片 一种不相交的子集所构成的集合S={S1,S2,...,Sn} 平衡二叉树图片 平衡二叉树插入新结点导致失衡的子树 调整: B树、B+树图片 对于在内部节点的数据,可直接得到,不必根据叶子节点来定位。 八叉树图片 八叉树(octree),或称八元树,是一种用于描述三维空间(划分空间)的树状数据结构。八叉树的每个节点表示一个正方体的体积元素,每个节点有八个子节点,这八个子节点所表示的体积元素加在一起就等于父节点的体积。一般中心点作为节点的分叉中心。 对于有线程系统: 对于无线程系统: 线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制 主机字节序又叫CPU字节序,其不是由操作系统决定的,而是由CPU指令集架构决定的。主机字节序分为两种: 32位整数0x12345678是从起始位置为0x00的地址开始存放,则: 大端小端图片 判断大端小端 可以这样判断自己CPU字节序是大端还是小端: #include 网络字节顺序采用:大端(BigEndian)排列方式。 在地址映射过程中,若在页面中发现所要访问的页面不在内存中,则产生缺页中断。当发生缺页中断时,如果操作系统内存中没有空闲页面,则操作系统必须在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间。而用来选择淘汰哪一页的规则叫做页面置换算法。 全局: 局部: 本节部分知识点来自《计算机网络(第7版)》 计算机网络体系结构: 通道: 通道复用技术: 主要信道: 三个基本问题: 点对点协议(Point-to-PointProtocol): 广播通信: IP地址分类: IP数据报格式: ICMP报文格式: 应用: 根据应用和执行的不同,路由表可能含有如下附加信息: 协议: 端口: 特征: TCP如何保证可靠传输: TCP报文结构 TCP首部 TCP:状态控制码(Code,ControlFlag),占6比特,含义如下: UDP报文结构 UDP首部 TCP是一个基于字节流的传输服务(UDP基于报文的),“流”意味着TCP所传输的数据是没有边界的。所以可能会出现两个数据包黏在一起的情况。 流量控制(flowcontrol)就是让发送方的发送速率不要太快,要让接收方来得及接收。 利用可变窗口进行流量控制 拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。 TCP的拥塞控制图 【TCP建立连接全过程解释】 【答案一】因为信道不可靠,而TCP想在不可靠信道上建立可靠地传输,那么三次通信是理论上的最小值。(而UDP则不需建立可靠传输,因此UDP不需要三次握手。) 【答案二】因为双方都需要确认对方收到了自己发送的序列号,确认过程最少要进行三次通信。 【答案三】为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。 【TCP释放连接全过程解释】 【问题一】TCP为什么要进行四次挥手?/为什么TCP建立连接需要三次,而释放连接则需要四次? 【答案一】因为TCP是全双工模式,客户端请求关闭连接后,客户端向服务端的连接关闭(一二次挥手),服务端继续传输之前没传完的数据给客户端(数据传输),服务端向客户端的连接关闭(三四次挥手)。所以TCP释放连接时服务器的ACK和FIN是分开发送的(中间隔着数据传输),而TCP建立连接时服务器的ACK和SYN是一起发送的(第二次握手),所以TCP建立连接需要三次,而释放连接则需要四次。 【问题二】为什么TCP连接时可以ACK和SYN一起发送,而释放时则ACK和FIN分开发送呢?(ACK和FIN分开是指第二次和第三次挥手) 【答案二】因为客户端请求释放时,服务器可能还有数据需要传输给客户端,因此服务端要先响应客户端FIN请求(服务端发送ACK),然后数据传输,传输完成后,服务端再提出FIN请求(服务端发送FIN);而连接时则没有中间的数据传输,因此连接时可以ACK和SYN一起发送。 【问题三】为什么客户端释放最后需要TIME-WAIT等待2MSL呢? 【答案三】 TCP有限状态机图片 域名: 标准格式: HTTP(HyperTextTransferProtocol,超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP是万维网的数据通信的基础。 请求方法 状态码(Status-Code) ssize_tread(intfd,void*buf,size_tcount);ssize_twrite(intfd,constvoid*buf,size_tcount);read()write()Socket中TCP的三次握手建立连接我们知道TCP建立连接要进行“三次握手”,即交换三个分组。大致流程如下: 只有就完了三次握手,但是这个三次握手发生在Socket的那几个函数中呢?请看下图: 从图中可以看出: 上面介绍了socket中TCP的三次握手建立过程,及其涉及的socket函数。现在我们介绍socket中的四次握手释放连接的过程,请看下图: 图示过程如下: 这样每个方向上都有一个FIN和ACK。 本节部分知识点来自《数据库系统概论(第5版)》 本节部分知识点来自《程序员的自我修养——链接装载库》 一般应用程序内存空间有如下区域: 栈保存了一个函数调用所需要的维护信息,常被称为堆栈帧(StackFrame)或活动记录(ActivateRecord),一般包含以下几方面: 堆分配算法: 典型的非法指针解引用造成的错误。当指针指向一个不允许读写的内存地址,而程序却试图利用指针来读或写该地址时,会出现这个错误。 普遍原因: 现在版本GCC把预编译和编译合成一步,预编译编译程序cc1、汇编器as、连接器ld MSVC编译环境,编译器cl、连接器link、可执行文件查看器dumpbin 编译器编译源代码后生成的文件叫做目标文件。目标文件从结构上讲,它是已经编译后的可执行文件格式,只是还没有经过链接的过程,其中可能有些符号或有些地址还没有被调整。 可执行文件(Windows的.exe和Linux的ELF)、动态链接库(Windows的.dll和Linux的.so)、静态链接库(Windows的.lib和Linux的.a)都是按照可执行文件格式存储(Windows按照PE-COFF,Linux按照ELF) PE和ELF都是COFF(CommonFileFormat)的变种 其他段略 在链接中,目标文件之间相互拼合实际上是目标文件之间对地址的引用,即对函数和变量的地址的引用。我们将函数和变量统称为符号(Symbol),函数名或变量名就是符号名(SymbolName)。 如下符号表(SymbolTable): Linux下的共享库就是普通的ELF共享对象。 共享库版本更新应该保证二进制接口ABI(ApplicationBinaryInterface)的兼容 libname.so.x.y.z 大部分包括Linux在内的开源系统遵循FHS(FileHierarchyStandard)的标准,这标准规定了系统文件如何存放,包括各个目录结构、组织和作用。 动态链接器会在/lib、/usr/lib和由/etc/ld.so.conf配置文件指定的,目录中查找共享库 使用CLion编写共享库 创建一个名为MySharedLib的共享库 CMakeLists.txt cmake_minimum_required(VERSION3.10)project(MySharedLib)set(CMAKE_CXX_STANDARD11)add_library(MySharedLibSHAREDlibrary.cpplibrary.h)library.h #ifndefMYSHAREDLIB_LIBRARY_H#defineMYSHAREDLIB_LIBRARY_H//打印HelloWorld!voidhello();//使用可变模版参数求和template #include 创建一个名为TestSharedLib的可执行项目 cmake_minimum_required(VERSION3.10)project(TestSharedLib)#C++11编译set(CMAKE_CXX_STANDARD11)#头文件路径set(INC_DIR/home/xx/code/clion/MySharedLib)#库文件路径set(LIB_DIR/home/xx/code/clion/MySharedLib/cmake-build-debug)include_directories(${INC_DIR})link_directories(${LIB_DIR})link_libraries(MySharedLib)add_executable(TestSharedLibmain.cpp)#链接MySharedLib库target_link_libraries(TestSharedLibMySharedLib)main.cpp #include IntWINAPI_tWinMain(HINSTANCEhInstanceExe,HINSTANCE,PTSTRpszCmdLine,intnCmdShow);int_tmain(intargc,TCHAR*argv[],TCHAR*envp[]);应用程序类型入口点函数嵌入可执行文件的启动函数处理ANSI字符(串)的GUI应用程序_tWinMain(WinMain)WinMainCRTSartup处理Unicode字符(串)的GUI应用程序_tWinMain(wWinMain)wWinMainCRTSartup处理ANSI字符(串)的CUI应用程序_tmain(Main)mainCRTSartup处理Unicode字符(串)的CUI应用程序_tmain(wMain)wmainCRTSartup动态链接库(Dynamic-LinkLibrary)DllMain_DllMainCRTStartupWindows的动态链接库(Dynamic-LinkLibrary)部分知识点来自《Windows核心编程(第五版)》 DllMain函数 FARPROCGetProcAddress(HMODULEhInstDll,PCSTRpszSymbolName//只能接受ANSI字符串,不能是Unicode);DumpBin.exe查看DLL信息在VS的开发人员命令提示符使用DumpBin.exe可查看DLL库的导出段(导出的变量、函数、类名的符号)、相对虚拟地址(RVA,relativevirtualaddress)。如: DUMPBIN-exportsD:\mydll.dllLoadLibrary与FreeLibrary流程图LoadLibrary与FreeLibrary流程图 DLL库的编写(导出一个DLL模块)DLL头文件 //MyLib.h#ifdefMYLIBAPI//MYLIBAPI应该在全部DLL源文件的include"Mylib.h"之前被定义//全部函数/变量正在被导出#else//这个头文件被一个exe源代码模块包含,意味着全部函数/变量被导入#defineMYLIBAPIextern"C"__declspec(dllimport)#endif//这里定义任何的数据结构和符号//定义导出的变量(避免导出变量)MYLIBAPIintg_nResult;//定义导出函数原型MYLIBAPIintAdd(intnLeft,intnRight);DLL源文件 //MyLibFile1.cpp//包含标准Windows和C运行时头文件#include //AsimpleprogramthatusesLoadLibraryand//GetProcAddresstoaccessmyPutsfromMyputs.dll.#include _start->__libc_start_main->exit->_exit 其中main(argc,argv,__environ)函数在__libc_start_main里执行。 intmainCRTStartup(void) 执行如下操作: 大致包含如下功能: 包含: C/C++发展方向甚广,包括不限于以下方向,以下列举一些大厂校招岗位要求。 【后台开发】 【PC客户端开发】 【游戏客户端开发】 【测试开发】 【安全技术】 【嵌入式应用开发】 【音视频编解码】 【计算机视觉研究】 打赏我一包辣条~ 本仓库遵循CCBY-NC-SA4.0(署名-非商业性使用-相同方式共享)协议,转载请注明出处,不得用于商业目的。