面试知识点:
-
字符串
-
strstr(str1,str2)的作用,用来判断str2是不是str1的子串
-
char* strchr(const char,char ch);说明:返回首次出现ch的位置的指针,返回的地址是被查找字符串指针开始的第一个与Val相同字符的指针,如果Str中不存在Val则返回NULL。
-
void *memcpy(void *dest, const void *src, size_t n);从src拷贝n个字符给dest
-
原型:void memmove( void dest, const void* src, size_t count );由src所指内存区域复制count个字节到dest所指内存区域。
-
memchr函数原型extern void *memchr(const void *buf, int ch, size_t count),功能:从buf所指内存区域的前count个字节查找字符ch。
-
-
extern
-
修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用
-
”extern声明不是定义,即不分配存储空间。
-
-
linux下优先级的问题3
-
int sched_get_priority_max(int policy); int sched_get_priority_min(int policy);
-
-
多方法交换x、y变量的值
-
异或
-
加减
-
指针
-
引用
-
-
指针与引用
-
★相同点:都是地址的概念;
指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。
-
★不同点:
-
指针是一个实体,引用只是一个别名
-
引用智能在定义的时候被初始化一次,之后不可变,指针可变,引用从一而终,指针见异思迁
-
引用没有const,指针有const,const的指针不可变
-
引用不能为空,指针可以为空
-
sizeof引用得到的事所指向的变量或者是对象的大小 而sizeof指针得到的是指针的大小;
-
引用类型是安全的,而指针不是,引用多了类型检查
-
指针的自增是地址的增加,
-
-
-
前置++与后置++
-
inline的作用
-
inline是函数定义的关键字,说你不敢该函数是内敛函数,内联函数会将代码块嵌入到每个调用该函数的地方,内联函数减少了函数的调用,使代码的执行效率提高,但是会增加目标代码的大小,最终会使得程序的代码段战友大量的内存;
-
为了解决一些频繁调用的小涵数大量消耗栈空间或者是叫栈内存的问题
-
-
二维数组的表示
-
普通的二维数组
-
一维数组表示
-
指针数组
-
指向指针的变量
-
-
ifndef 作用是防止头文件的重复定义
-
const与define的比较
-
define只是简单的字符替换没有类型检查,在编译的预处理阶段起作用,不能调试,在预编译阶段就已经替换掉了,
-
const有类型安全判断,在编译、运行的时候起作用
-
-
KMP算法 maxl、next、nextval三个数组;
-
函数调用方式
-
按值传递
-
按引用传递
-
按指针传递
-
-
重载函数、覆盖、隐藏
-
重载:
-
在同一个作用域,函数名字相同,参数列表不同(参数个数或者类型,参数类型和个数不同),返回值类型可相同可不同,这种情况叫做c++的重载;
-
达到的效果:调用函数名相同的函数,会根据实参的类型和实参顺序以及实参的个数选择相应的函数;
-
c++函数重载也是一种静态多态(又叫做静态联编,静态绑定,静态决议)
-
-
覆盖(重写)
-
虚函数:类的成员函数前面加上virtual关键字
-
覆盖的条件是 父类是虚函数
-
概念:在子类中定义了一个同父类完全相同的函数,则称这个子类(重写)覆盖了父类这个虚函数
-
注意 ,这个子类的函数也是虚函数
-
达到的效果:
-
子类重写了父类的虚函数,调用的时候是调用的子类内部重写的虚函数,(动态多态的实现);
-
如果用一个父类的指针(或引用)指向(或引用)子类对象,那么这个父类的指针引用或调用这个重写的虚函数,调用的是子类的虚函数;相反如果引用或者指向的是父类的对象那么调用的是父类的虚函数
-
-
-
隐藏:
-
是指在不同的作用域中(子类和父类)函数名字相同,不能构成重写的都是重定义(隐藏)
-
适用范围:不仅仅是成员函数还有成员变量
-
直接效果:如果子类和父类中有相同名字的成员,那么在子类中将父类隐藏;隐藏以后的效果就是无论在子类的内部还是外部都调用子类的成员函数;全部访问子类的成员;
如果在子类内内部或者是外部(通过子类成员)访问同名成员函数,则需要函数调用的规则来调用子类的同名成员函数 ;
-
-
-
-
双向链表的插入与删除
-
插入
-
删除:是不是头结点(只有一个结点、多个结点)是不是尾结点
-
-
二叉树的各种遍历方式;
-
读写线程和一个队列;
-
当队列为空的时候,读取线程必须等待写入数据向队列中写入数据。也就是队列为空的时候读取线程必须等待队列中有数据;
-
当队列满的时候,写入线程必须等待读取线程读取队列中的内容;
-
是否需要互斥:
-
-
STL线程安全问题
-
多个读取者是安全的
-
多对不铜容器的多个写入者是安全的
-
对同一容器 读写的时候 需要程序员自己控制
-
每次调用成员函数,迭代器,调用算法的期间内 需要锁定;
-
代码:
-
vector<int> v; ... getMutexFor(v); vector<int>::iterator first5(find(v.begin(), v.end(), 5)); if (first5 != v.end()) { // 这里现在安全了 *first5 = 0; // 这里也是 } releaseMutexFor(v); //面向对象的解决方案是创建一个lock类: template <typename Container> // 获取和释放容器的互斥量 class Lock { // 的类的模板核心; public: // 忽略了很多细节 Lock(const Containers container) : c(container) { getMutexFor(c); // 在构造函数获取互斥量 } ~Lock() { releaseMutexFor(c); // 在析构函数里释放它 } private: const Container& c; };
-
-
-
内存池、线程池
-
TCp的流量控制和拥塞控制
-
流量控制:所谓的流量控制就是让发送方的发送速率不要太快,让接收方来得及接收,利用滑动窗口可以很方便的在tcp连接上实现对发送方的流量控制;tcp的窗口单位是字节不是报文段;发送方的发送窗口不能超过接收方的接收窗口的数值;
-
拥塞控制:
-
原理:在某段时间内,若对网络中的某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变化,这种情况成为拥塞;拥塞的问题往往是整个系统的和部分不匹配,只有各部分平衡了就解决了问题;
-
与流量控制的差别:
-
拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或者链路不过载;
-
流量控制指的是点对点的通信量的控制,是端到端的问题;流量控制要做的事控制发送端发送属于的速录,使得接收端来得及接收;
-
-
拥塞控制设计:很难设计,是一个动态的问题;许多情况下拥塞控制机制本身成为引起网络恶化甚至是死锁的原因;
-
拥塞控制方法:即慢开始、拥塞避免、快重传、快恢复;
-
慢开始
-
拥塞避免
-
快重传和快恢复;
-
-
-
-
面向对象、封装、继承、多态问题、多态的实现机制;
-
封装:利用抽象数据类型将数据和基于数据的操作封装在一起,构成一个不可分割的独立实体数据保护在抽象数据类型的内部,尽可能的隐藏其内部的细节,只保留一些对外接口与外部发生联系;
-
继承:使用现有类;
-
多态
-
静态多态:重载
-
动态多态:覆盖;
-
-
-
内联函数
-
内敛函数在编译的时候展开
-
内敛函数什么时候不展开:
-
内联函数内不允许使用循环语句和开关语句(switch),如果有这些语句就视为普通函数;
-
内联函数只适合于只有1-5行的函数 如果含有许多大语句则不合适;
-
使用函数指针来调用内联函数;
-
-
-
初始化成员列表有什么作用?什么成员必须在成员初始化列表中进行初始化?
-
作用:
-
变量的初始化;
-
提高构造函数的性能;
-
在派生类中可以跳过基类构造函数,直接进入复制操作;
-
-
:
-
常量成员
-
引用类型
-
没有默认构造函数的类类型,使用初始化列表不必调用默认构造函数来进行初始化,而是直接调用拷贝构造函数来初始化;
-
成员是按照它们在类中出现的顺序进行初始化的,而不是按照在初始化列表中的顺序进行初始化的;
-
-
-
指针与引用的区别(同5)
-
创建空类 那些成员是系统默认的(6个)
-
空类
-
缺省构造函数
-
拷贝构造函数
-
析构函数
-
赋值运算符
-
两个取值运算符
-
-
空类的对象大小 为什么是1
-
一个对象的大小大于等于所有非静态成员大小的总和3
-
空类也可以被实例化,每个实例在内存中都有一个独一无二的地址;为了达到这个目的,编辑器通常会给一个空类隐含的加一个字节,这样空类在实例化后再内存得到一个的地址所以为1;
-
类的静态成员编译的时候被放在global data members中,它是类的一个数据成员,但是它不影响类的大小,不管类产生了多少的实例,还是派生了多少新的类,静态成员永远只是一个实体存在,而类的非静态数据成员只有在实例化的时候才会存在;静态数据成员是一种特殊的全局变量;
-
-
各种数据类型的大小:只有指针的大小不一样;
type 32bit 64bit char 1 1 short 2 2 int 4 4 long 4 4 long long 8 8 float 4 4 unsigned int 4 4 double 8 8 pointer 4 8
-
-
100亿条文本记录的文本文件,取出重复数最多的前十条
-
100亿个大概需要100GB,不可能一次性加载进内存进行操作;所以必须要拆分
-
把100亿分成10000份,没份大约是10MB;可以加载到内存;Map
-
f(ip)=ip%10000; 相同的加载进一个文件;
-
-
然后再10Mb的小文件加载进内存,统计戳最多的那个ip;
-
-
常见的异常跑出的种类:
-
Error 代表了编译和系统的错误,不允许捕捉
-
Runtime Exception 运行时异常
-
Exception
-
throw用户自定义;
-
-
长连接、短连接
-
短连接: 连接-->传输数据-->关闭链接
socket链接后发送后接受哦玩数据后马上断开;
像web网站的http服务一般都用短连接,因为长连接对于服务端来说会消耗一定的资源。并发量大。
-
长连接 链接--->传输数据----->传输数据---->。。。关闭链接
建立socket链接之后不管是否使用都保持链接,安全性差;
适用于操作频繁,点对点通讯,而且连接数不能太多,每个链接都需要三不握手,如果每个操作都是先连接,再操作速度会很低;
数据库的链接用长连接;
-
-
const
-
修饰节本的数据类型
-
修饰一般常量和数组;
-
修饰指针变量*和引用变量&
-
-
const应用到函数中
-
作为参数的const修饰符
-
作为函数返回值的const修饰符
-
类中的成员函数:A fun()const 其意义是不能修改所在类的任何变量;
-
-
应用到类中
-
const修饰类对象,定义常量对象
-
-
回调函数
-
a调用b,但是b的实现由调用a
-
作用:把要处理执行的任务携程一个写成,将这个函数和某一个事件或者是中断建立关联
-
回调函数的作用 决定权交给客户端,与客户端进行交流,通过客户端进行输入,荣通过客户端来进行输出;
-
-
内存溢出与内存泄漏
-
内存溢出:程序要求的内存超出了系统所能分配的范围;(栈满还入栈,栈空还出栈);
-
内存泄漏:分配出去的内存无法回收(不再使用的对象或者是变量仍然占用内存空间);
-