0%

附加

struct和union的区别

memcpy实现

要 考虑函数的鲁棒性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void mymemcpy(void* src, void* dst, int len){
// 多字节复制 要判断两个地址是不是有重叠,如果有重叠要反向赋值
if(!dst || !src) return;
int m = len / sizeof(int);
int n = len % sizeof(int);

//倒序
if(src + len > dst && dst > src){
char* p1 = (char*)(src + len - 1);
char* p2 = (char*)(dst + len - 1);
while(n--){
*p2-- = *p1--;
}
p1++; p2++; // 注意内存覆盖
int* p3 = (int*)p1;
int* p4 = (int*)p2;
p3--; p4--;
while(m--){
*((char*)p4++) = *((char*)p3++);
}
}else{
// 正向拷贝
}
}

手写一下智能指针

weak_ptr 内部实现, 可以实现观察者模式

这是因为 weak_ptr 只会增加弱引用计数,它不会影响指向的对象的生命周期,多以可以在被观察者中使用weak_ptr去指向观察者,观察者对象的释放与否都不会影响被观察者的运行结果,当被观察者需要向观察者传递消息时只需要将弱指针提升为智能指针再去访问。

解决内存泄漏….

智能指针是线程安全的嘛

引用计数是原子的,线程安全的,对共享内存的操作不是,多线程写会出现问题

Hash 怎么做成线程安全

Hash表本质是一个数组,可以直接全表上锁,但是这样锁冲突的概率很大。可以分段上锁,因为本质上 就是一个线程修改数组中的某一个元素,同时另一个线程可以修改数组的其他元素。只有当要hash扩容的时候才需要全表上锁

菱形继承

主要总结了三块儿知识点

  1. 普通的菱形继承的内存分布,比如 D: public B1, public B2, 内存模型可以看作 [B1:B 组成的一块儿内存] + [B2:B组成的一块儿内存] + [D 自己定义的一块儿内存],就是三段儿。但是这样会有二义性,比如B1里面的变量b 和 B2里面的变量b,访问就要家类型限定,来指定你要访问的是 B1 还是 B2 里面的。
  2. 虚继承的菱形继承问题:首先 虚继承就是说 子类如果定义了父类中存在的变量,那么就不再覆写,将父类的变量放在内存最后,同时在首地址需要存放一个 vbptr ,vbptr第一项指示相对起始虚表指针的偏移,第二项来指示基类变量的偏移,这样通过 vbptr可以直接跳转到基类变量上。那么菱形继承的内存布局就是 [B1:覆写B的变量和B1独有的变量] + [B2:B2覆写B的变量和B2独有的] + [D自己定义的变量] + [基类B的一份变量];也就是说 可以指定 B1/B2/B 来选择要访问谁的变量
  3. 带虚函数的菱形继承(不考虑虚继承):这种情况下 首先很重要的- 一个 D对象只能用 B1 或者 B2类型的指针去指向,而不能用 B的指针指向D会报错。会有两个虚函数表 B1的虚函数表 + B2 的虚函数表; D自己单独写的新的虚函数被放在了第一个虚表中的最后。B1虚表中有完备的 B1+B类的所有虚函数,如果D重写了就替换,同理 B2 虚表中有完备的B2+B的所有虚函数 ,这样无论是取B1指针指向D对象 还是 B2指针指向D对象,都能调用B1中所有的虚函数 或者 B2中的所有虚函数
  4. 带虚函数的菱形继承(考虑虚继承)….

参考链接 参考链接

设计模式:解释一下proactor。

const 的作用,作用于函数 的特点

  • const 作用于局部变量它存放在栈中 可以通过地址间接修改变量值 作用于全局变量 存在只读数据存储区,如果修改它的值会产生运行错误
  • const 作用于成员函数 那么 代表它不会修改所有非 static 的成员变量(实际就是 const this 指针实现);因此const 对象也就只能调用 const 修饰的成员函数

野指针,空指针的区别;内存泄漏问题;如何解决

在不知道头节点的情况下删除某个节点

C++能否在有参构造函数中调用无参构造函数,无参构造函数中如果有修改类成员会不会对当前正在构造的类产生影响,这种调用方式有什么优势或者缺点。

可以 会修改 代码复用

面向过程和面向对象各自的优缺点

内存屏障,volatile作用,是否具有原子性,使用volatile会对编译器有什么影响

可执行文件的文件格式(ELF文件格式)

C++的构造析构顺序

怎么用一个指向子类的基类指针调用基类的虚函数

(强制转换或者指明作用域d->Base::fun())

写一个字符串类的移动构造,拷贝构造,赋值构造并模拟这几个过程

快排的时间复杂度,什么时候最坏,什么时候最好

什么情况下会出现段错误,为什么段错误程序会直接终止

大文件排序问题

题目:有一个大文件,里面记录了若干数字,把这些数字进行排序。文件大小远大于内存大小

基本思想都是要归并 将大文件分成多个小文件 分别排序,然后合并的。最后合并的时候每个小文件只读入一部分,同时留一个输出缓冲区用于存储已经排好的数据。等输出缓冲区满了之后就把他存到外存然后清空输出缓冲区。

topK的问题类似,一部分一部分的读入 用堆选择topK大的数据

参考

image-20210619101337401
image-20210619101325346
image-20210619101347480
image-20210619102250262
image-20210619103938330
image-20210619105006188
image-20210619105210585
image-20210619105741668
image-20210619105924199
image-20210619111011948