一.基础知识
1.一个字节8位:0xFF,255,char
两个字节16位:0xFFFF,65535,short
4个字节32位:0xFFFFFFFF,42亿,DWORD
2.大端小端
大端:高位字节排放在内存的低地址端,低位字节排放在内存的高地址端(同人类读写数值的方法)
低地址 --------------------> 高地址
0x12 | 0x34 | 0x56 | 0x78
小端:低位字节排放在内存的低地址端,高位字节排放在内存的高地址端(个人电脑储存形式)
低地址 --------------------> 高地址
0x78 | 0x56 | 0x34 | 0x12
个人电脑,Intel或AMD的x86/x64架构是小端字节序,ARM既有大端也有小端,网络通信上为大端模式
转换函数:ntohl(a),hton(a)
如何进行转换:
对于字数据(16位):(程序中的“\”表示当前行和下一行是同一行)
#define BigtoLittle16(A) (( ((uint16)(A) & 0xff00) >> 8) | \
(( (uint16)(A) & 0x00ff) << 8))
#define BigtoLittle32(A) ((( (uint32)(A) & 0xff000000) >> 24) | \
(( (uint32)(A) & 0x00ff0000) >> 8) | \
(( (uint32)(A) & 0x0000ff00) << 8) | \
(( (uint32)(A) & 0x000000ff) << 24))
3.申请内存
malloc/free与new/delete区别:前者可以用于指定大小内存,也可以用于结构体,如PrivateRsa = (RSA*)malloc(sizeof(RSA));,后者只用于固定大小,如结构体
free释放内存后,需要NULL(不置NULL导致指针成为“野指针”,诱导误操作),
4.delete 和 delete []的区别
delete 释放new分配的单个对象指针指向的内存
delete[] 释放new分配的对象数组指针指向的内存
5.将“引用”作为函数参数有哪些特点?
在内存中并没有产生实参的副本,它是直接对实参操作
6.在什么时候需要使用“常引用”?const int &ra=a;
如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用
7、结构体与联合有和区别?
联合体所有成员共用一块地址空间
8.重载(Overloading):重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型。
重写(Overriding):父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某方法与其父类有相同的名称和参数
覆盖:派生类覆盖基类的虚函数,实现接口的重用,基类中必须有virtual关键字
9.请说出const与#define 相比,有何优点?
被Const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性
const 常量有数据类型,编译器可以对其进行安全检查,还可以调试
10、关键字static的作用
1)函数体内: static 修饰的局部变量作用范围为该函数体,不同于auto变量,其内存只被分配一次,因此其值在下次调用的时候维持了上次的值
2)文件内:static修饰全局变量或全局函数,可以被改文件内的所有函数访问,但是不能被模块外的其他函数访问,使用范围限制在声明它的模块内
3)类中:修饰成员变量,表示该变量属于整个类所有,对类的所有对象只有一份拷贝
4)类中:修饰成员函数,表示该函数属于整个类所有,不接受this指针,只能访问类中的static成员变量
注意和const的区别!!!const强调值不能被修改,而static强调唯一的拷贝,对所有类的对象
11、C++的内存管理
在C++中,内存被分成五个区:栈、堆、自由存储区、静态存储区、常量区
栈:存放函数的参数和局部变量,编译器自动分配和释放
堆:new关键字动态分配的内存,由程序员手动进行释放,否则程序结束后,由操作系统自动进行回收
自由存储区:由malloc分配的内存,和堆十分相似,由对应的free进行释放
全局/静态存储区:存放全局变量和静态变量
常量区:存放常量,不允许被修改
12、深拷贝和浅拷贝的区别
深拷贝和浅拷贝可以简单的理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,如果资源重新分配了就是深拷贝;反之没有重新分配资源,就是浅拷贝。
13.友元函数
有元函数是可以访问类的私有成员的非成员函数。它是定义在类外的普通函数,不属于任何类,但是需要在类的定义中加以声明。
friend 类型 函数名(形式参数);
一个函数可以是多个类的友元函数,只需要在各个类中分别声明。
6、 C++的四种强制转换
类型转化机制可以分为隐式类型转换和显示类型转化(强制类型转换)
(new-type) expression
new-type (expression)
隐式类型转换比较常见,在混合类型表达式中经常发生;四种强制类型转换操作符:
static_cast、dynamic_cast、const_cast、reinterpret_cast
1)static_cast :编译时期的静态类型检查
static_cast < type-id > ( expression )
该运算符把expression转换成type-id类型,在编译时使用类型信息执行转换,在转换时执行必要的检测(指针越界、类型检查),其操作数相对是安全的
2)dynamic_cast:运行时的检查
用于在集成体系中进行安全的向下转换downcast,即基类指针/引用->派生类指针/引用
dynamic_cast是4个转换中唯一的RTTI操作符,提供运行时类型检查。
dynamic_cast如果不能转换返回NULL
源类中必须要有虚函数,保证多态,才能使用dynamic_cast<source>(expression)
3)const_cast
去除const常量属性,使其可以修改 ; volatile属性的转换
4)reinterpret_cast
通常为了将一种数据类型转换成另一种数据类型
10.C++11有哪些新特性
1)关键字及新语法:auto、nullptr、for
2)STL容器:std::array、std::forward_list、std::unordered_map、std::unordered_set
3)多线程:std::thread、std::atomic、std::condition_variable
4)智能指针内存管理:std::shared_ptr、std::weak_ptr
5)其他:std::function、std::bind和lamda表达式
11.线程池的实现
12.虚函数表
11.程序奔溃类型:
1 读取未赋值的变量: int a, b;int m = multiply(a, b);注意其错误特征:“The variable is being used without being initialized”
2 函数栈溢出函数栈溢出:
(1)定义了一个体积太大的局部变量 int buf[1024*1024*16];
(2)函数嵌套调用,层次过深(如无穷递归)
3.数组越界访问
4指针的目标对象不可用
空指针 Object* obj = NULL;p->id
野指针: 指针未赋值 Object* p;p->id;(p的有地址,是乱的,容易造成程序意想不到的错误)
12.斜杠与反斜杠:
斜杠/表示除法,分隔。在windows系统中通常用来分隔命令行参数,/表示选项等
反斜杠\,在windows系统中用来表示目录。
而在unix系统中,/表示目录。由于web遵循unix命名,所以在网址(URL)中,/表示目录。
在C中 \ 是转义字符,如下所示 '\0'
二.tcp/ip
1.OSI模型有7层结构,每层都可以有几个子层。 OSI的7层从上到下分别是 7 应用层 6 表示层 5 会话层 4 传输层 3 网络层 2 数据链路层 1 物理层 ;其中高层(即7、6、5、4层)定义了应用程序的功能,下面3层(即3、2、1层)主要面向通过网络的端到端的数据流。
应用层:TELNET,HTTP,FTP
表示层:定义数据格式及加密,ASCII
会话层:它定义了如何开始、控制和结束一个会话,包括对多个双向消息的控制和管理,以便在只完成连续消息的一部分时可以通知应用,从而使表示层看到的数据是连续的
传输层:TCP,UDP,数据包一旦离开网卡即进入网络传输层
网络层:IPV4 IPV6,进行逻辑地址寻址,实现不同网络之间的路径选择
数据链路层:立逻辑连接、进行硬件地址寻址、差错校验 [2] 等功能
物理层:建立、维护、断开物理连接
2.TCP在传输之前会进行“三次握手”,断开“四次挥手”。
3.高并发:多线程,多进程,完成端口,网络分发,数据库优化等等
1).网络负载均衡架构设计
2).数据库负载均衡架构设计
3).消息队列负载均衡架构设计
manggodb支付千亿条记录
4.五种模型
1.select模型:将套接字放到集合中,select后,轮询查看套接字是否仍然处于读集中。默认64个连接,最大可以设置1024个
2.异步选择模型:int WSAAsynSelect(SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent),缺点是需要窗口,而且单窗口性能也不佳
3.事件选择模型:WSAEventSelect:在出现感兴趣的 socket事件时,系统会将相应WSAEVENT事件设为传信。只有有事件发生,WSAWaitForMultipleEvents(...)就会返回
缺点是该模型每次只能等待64个事件
4.重叠I/O模型: WSAWaitForMultipleEvents(...) 就返回
5.完成端口:创建完成端口对象CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0),工作者线程调用 GetQueuedCompletionStatus 来轮询完成端口队列。
完成端口内部提供线程池的管理,同时可以根据CPU的个数灵活的决定线程个数,这样随着系统内安装的CPU数量的增多,应用程序的性能也可以线性提升
异步的,CreateIOCompleTionPort
GetCompleTionStatus
PostQueuedCompletionStatus
具体:https://blog.csdn.net/piggyxp/article/details/6922277
三.windows消息机制
PostMessage 不等返回、SendMessage需要等返回,GetMessage获取消息后,删除队列里消息(死等),PeekMessage不等
Windows消息循环: Windows 操作系统为每个线程维持一个消息队列,当事件产生时,操作系统感知这一事件的发生,并包装成消息发送到消息队列,应用程序通过GetMessage()函数取得消息并存于一个消息结构体中
Windows消息提供了应用程序与应用程序之间、应用程序与Windows 系统之间。Windows 系统中有两种消息队列,一种是系统消息队列,另一种是应用程序消息队列
四、容器
向量 std::vector<CAttep> Attemp; 连续存储的元素
链表 std::list<CAttep> a;由节点组成的双向链表,每个结点包含着一个元素
队列 std::<queue>a 先进先出的执的排列
映射 std::map<CAttep>a; 由{键,值}对组成的集合
多重映射 multimap 允许键对有相等的次序的映射
集合 set由节点组成的红黑树,set是用红黑树的平衡二叉索引树的数据结构来实现的,插入时,它会自动调节二叉树排列,把元素放到适合的位置,确保每个子树根节点的键值大于左子树所有的值、小于右子树所有的值,插入重复数据时会忽略
多重集合 multiset 允许存在两个次序相等的元素的集合 <set>
迭代器:vector<int>::itertor it = v.bein();
五、数据库
1.数据库优化
1)优化数据库表结构.varchar,char尽可能不要使用NULL值
2)优化查询语句:尽量避免全表扫描,包括但不限于where子句条件横真或为空,LIKE,<>、!=,is null,
多条件查询时,把简单查询条件或则索引列查询置于前面
请尽量指定需要查询的列,不要偷懒使用select *,
大些的查询关键字比小写快一点点
在索引字段上查询尽量不要使用数据库函数,不便于缓存查询结果
当只要一行数据时,请使用LIMIT 1,如果数据过多,请适当设定LIMIT,分页查询
3)建立索引
4)大表拆分:垂直分表是按照日期等外部变量进行分表,水平分表是按照表中的某些字段关系,使用hash映射等分表
5)添加本地缓存和redis缓存
6)读写分离或者分布式
2.触发器:CREATE TRIGGER audit_log AFTER INSERT ON COMPANY
BEGIN
INSERT INTO AUDIT(EMP_ID, ENTRY_DATE) VALUES (new.ID, datetime('now'));
END;
3.事物处理
原子性:事务必须是一个自动工作的单元,要么全部执行,要么全部不执行。
一致性:事务结束的时候,所有的内部数据都是正确的。
隔离性:并发多个事务时,各个事务不干涉内部数据,处理的都是另外一个事务处理之前或之后的数据。
持久性:事务提交之后,数据是永久性的,不可再回滚。
begin tran
commit tran
六.设计模式
七.其他
1.内存泄露检测工具:
1.vs编译器
2.Visual Leak Detector
#include <vld.h>
2.常用api:
_atoi64
_wtoll
LOWORD。WORD wIndex=LOWORD(dwAndroidID);
HIWORD m_wRoundID!=HIWORD(dwAndroidID)
3.几种经典架构
4.ace框架
5.boost
6.书本:《C++程序设计语言》、《C++primer》、《VS 实战宝典》《window网络编程》