移动构造和移动赋值函数重载/函数重写/函数重定义
虚函数是什么?
非静态成员函数前加virtual
如何实现多态?
派生类+virtual 返回值 函数名 参数一致(除协变) 改写内容 虚函数表(重写/覆盖) 切片 虚函数指针 虚表 虚函数地址
多态的原理
虚函数表 切片
重写后 生成虚函数指针 指向 虚函数表 存的是虚函数的地址
纯虚函数
=0
抽象类
类中有纯虚函数的类 没法创建对象 除非继承它的子类 重写纯虚函数
什么是重定义?
基类/派生类 同名函数 不构成重写的函数
为什么构造函数不能是虚函数? 虚函数--内存
为什么析构函数要是虚函数?
输入/输出(结果未知,需要函数给结果的参数)/输入输出型参数 const&/*/&
substr?sub(pos,lenth) 从pos位置开始 切lenth个字符
string substr (size_t pos = 0, size_t len = npos) const;这个const修饰的是谁?
这个const表示,函数体内的任何变量都不能被修改。
静态成员在类中的特点?
1.为本类型所有对象所共有
在类未实例化时,非静态函数可以调用静态成员吗?可以,但静态变量要在类外定义 注意:静态成员变量在类中仅仅是一个声明,类实例化时也不会对静态成员实例化,所以要在类外定义
在类中,只要没有实例化,除了静态成员函数外,类中所有成员都只是声明
静态成员函数:只能调用静态成员变量(在类外经过定义的)/函数
静态成员变量:类中声明 类外定义
友元函数的特点?
1.友元函数所在类要在上方
2.友元函数要在类内声明,类外定义(编译器问题)
class B { public: void testB();//声明 }; class A { private: friend void B::testB(); void testA() { std::cout << "a:" << a << std::endl; } private: int a=0; }; void B::testB()//定义 { A a; a.testA(); }
Linux文件权限
- --- --- ---
类型 拥有者权限 拥有者所在组权限 other权限
文件实际权限=mask&(~umask) |||| 文件mask=0666 文件夹mask=0777 |||umask=002(八进制)(八进制一位可以表示3位二进制)
chmod u/g/o/a +r/w/x 文件名/文件目录
僵尸进程与孤儿进程
僵尸进程(是一个数据结构,保留了pid,退出状态等等)--父进程未exit,但没有调用wait/waitpid,而子进程退出了(子进程所占用的资源释放了),子进程成为僵尸进程,其包含的信息无法得到释放。
孤儿进程:父进程退出了,子进程仍在运行,则子进程被init进程领养,成为孤儿进程
const与*
const在*左,修饰的是指针指向的内容
const在*右,修饰的是指针本身
计算结构体大小
对齐数 min(成员对齐数,默认对齐数)
最大对齐数 max(成员对齐数)
结构体嵌套结构体?(将嵌套的结构体看作成员对待)
struct { int a; float b; struct { char a1; int b1; double c; }; }s; ------------------ struct { int a; float b; char a1; int b1; double c; }s;
守护进程如何实现的?为什么要忽略信号?
自成进程组 自成会话的进程,称为守护进程
1.忽略信号---SIGNAL(SIGCHILD,SIG_IGN)(子进程由内核回收)SIGNAL(SIGPIPE,SIG_IGN)(如果client端关闭,不让server端执行SIGPIPE的默认动作(终止进程))
2.fork
3.setsid
4.设置工作目录
std::bind?
堆:
向下调整:条件(左右子树必须是堆结构)
使用场景:
堆的删除(指堆顶元素与堆尾元素交换,并对新的堆顶元素使用向下调整)why?
直接删除堆顶元素-->左右子树失序-->(向下)重新建堆-->时间复杂度=O(N) |||| 交换元素-->左右仍为堆结构-->向下调整算法调整堆结构-->时间复杂度=O(log(n))
向下调整建堆(从最后一个非空叶子结点开始)
向上调整:
使用场景:
向堆中插入元素,使用向上调整算法调整堆结构 时间复杂度 O(log(n))
虚拟存储??即虚拟地址空间 为什么有?直接访问物理地址篡改内存数据 || 直接分配物理地址 ,进程很多 内存不够
代码区 静态存储区 BSS 堆区 共享区 栈区 内核空间
32位机器 3GB 用户 1GB内核 保留区
OS管理->task_struct(PCB)->管理进程
活锁是什么??
页框是什么??物理内存的一个基本单位 4KB
snprintf的用法?
int snprintf ( char * s, size_t n, const char * format, ... );
将n个字节的内容,按照format("wo shi ni die %s %s")的格式,往s指向的缓冲区里面存储,...是可变参数,个数与format中的格式标识符(%s %d)数量一致
vsnprintf的用法?(vsnprintf上一层必须是 (const char* format,...))
int vsnprintf (char * s, size_t n, const char * format, va_list arg );
将n个字节的内容,按照format("wo shi ni die %s %s")的格式,往s指向的缓冲区里面存储,
可变参数?
char argv[10]与char*?
数组名是指向首元素的地址,数组名的类型取决于数组元素的类型 例如 char argv[10]指向 char 所以它的类型是char*
&数组名,表示的是取整个数组的地址 ,这个地址的类型是char[10]*
缓存的使用场景??
信号量??
对临界资源做更细粒度的管理
什么是序列化什么是反序列化?
快速排序
归并排序
%两边必须是整数
智能指针具体是如何实现的?above
是一个类模板
类成员有一个模板类型的指针 T* ptr
构造函数传入指针,使用该指针对模板类型的指针初始化(即赋值)
析构函数 delete ptr
为了让这个类模板与正常指针使用无异,会对运算符重载
T* operator->() T& operator *()
智能指针的具体类型
1.auto_ptr 已经被废弃 c++98
why?当多个auto_ptr指向同一个对象时,无法判断auto_ptr是否有对该对象的拥有权?允许拥有权的转移多次析构问题
2.unique_ptr c++11 为了解决auto_ptr的问题 独占智能指针 一个对象只能被一个智能指针指向
拷贝构造/与赋值运算被delete了
可以移动赋值(by转移所有权)鸡肋
移动构造是啥?explicit 是? noexcept是?
3.shared_ptr 一个对象被多个智能指针所指向 它是如何做到的
它通过引用计数 解决的是赋值时 多个sp指向同一个对象 而造成重复析构的问题,但是不能解决初始化时的如下场景
test* a = new test();
tsj::shared_ptr p1(a);
tsj::shared_ptr p2(a);
循环引用问题 怎么造成的?例如: 两个双向链表,相互引用 两个类
4.为了解决上述问题,专门引入了weak_ptr 如何实现的?不是RAII智能指针 ,当存在循环引用的问题时,就使用weakptr
引用计数 不++/-- 不管理资源、
类默认会生成什么函数?
构造 析构 拷贝构造 赋值重载 取地址/const取地址的重载
空类的大小是多少?为什么
1
如果空类为0,就意味着它在没有存储在内存中,没有地址,那么就无法实例化对象。找不到
地址冲突,如果两个空类都为0,实例化对象可能会被分配到同一地址,不符合对象地址唯一性
类中隐形的存储了其他信息 例如类型信息、虚函数表指针等
引用的原理?左值引用和右值引用(移动构造)
vector 迭代器失效
list
hashtable
unordered_map/unordered_set 底层是哈希表/哈希桶
unordered_map/unordered_set 不支持重复元素插入 减少哈希冲突 提高索引效率
单例模式:确保类只有一个实例。在内存中只创建一个该类的实例,在程序中多次使用同一个对象且作用相同,有需要调用的地方都共享这一单例对象,节省内存
懒汉模式 判断类是否进行实例化,yes->返回该类的实例 no->类实例化,返回类实例
饿汉模式 类加载时已经创建好了实例对象,等待程序调用
引入锁,确保只创建了一个实例 double check提高效率
网络字节序
不同的主机存在 大端-小端 数据存储的方式
网络数据在放送的时候统一以大端方式发送 高位低地址
发送:
小端机:将数据按大端方式发送
接收:
小端机:将数据转成小端
序列化 网络传输时,数据以二进制方式传送
反序列化 上层获取数据时,将二进制内容转换成应用层能识别的格式
AVL树/红黑树
AVL:
平衡二叉树,
LL:左旋
RR:右旋
LR
RL
static 修饰
局部变量 生命周期延长了 生命周期随所在源文件
全局变量 外部链接属性-->内部链接属性 只能在所在源文件使用 生命周期随程序
函数 外部链接属性-->内部链接属性 只能在所在源文件使用 生命周期随所在源文件
移动构造的本质:将一个对象(右值类型,即将亡值)的资源转移给另一个对象,是一种浅拷贝,移动构造函数通常使用右值引用作为参数
左值:可以取地址的值,可以被修改的值,左值指的是那些可以出现在赋值语句左边的表达式
右值:不能取地址,不可被修改的值,例如常量、临时变量、匿名对象,右值则是指那些不能出现在赋值语句左边的表达式
string与vector的迭代器底层是指针,因为他们的底层空间是连续的
list迭代器底层是迭代器类,是对结点指针的封装,因为list的底层空间是不连续的,而迭代器的意义就是让使用者不关心底层结构,可以用简单统一的方式对容器内的数据进行访问。
菱形继承的形态?
多态 1.虚函数覆盖 2.父类指针/引用调用
虚函数表指针->虚函数表->函数地址 父类指针或引用调用虚函数 为什么?切片 可以是父类对象吗?不能因为, 切片时调用的时拷贝构造,父类对象的虚表指针永远指向的是父类的虚函数表
菱形虚拟继承 虚基表指针->虚基表->当前类对象位置距离公共虚基类的偏移量
关于将析构函数设置为虚函数
1.不这样设置可能会导致资源泄露
2.设置成了虚函数后 编译器会调用子类的析构函数(虚函数表),编译器行为,为了保证多态<当你执行 delete ptr; 时,由于基类的析构函数是虚函数,因此程序会在运行时识别出 ptr 指向的是子类对象,并调用子类的析构函数来正确释放该对象的资源。>
不设置的话只会调用父类的析构函数 虚函数间不构成多态,对象类型是什么就调用谁的虚函数,跟类型有关
析构函数不会被继承
位图 templateclass{vector}
布隆过滤器 使用多个hash函数的位图 string to int hash冲突
哈希切分 就是利用hash函数 将大文件切成一个个小文件
unordered_set?