补充面试

This commit is contained in:
estomm
2021-04-19 19:25:49 +08:00
parent b41c101312
commit 44593ed721
5 changed files with 132 additions and 0 deletions

View File

@@ -113,3 +113,8 @@ crbegin(),crend()|尾后迭代器。用来从后到前遍历元素。不可以
![](image/2021-03-05-21-13-26.png)
## 容器删除问题
1. 对于序列容器vector,deque来说使用erase(itertor)后后边的每个元素的迭代器都会失效但是后边每个元素都会往前移动一个位置但是erase会返回下一个有效的迭代器
2. 对于关联容器map set来说使用了erase(iterator)后当前元素的迭代器失效但是其结构是红黑树删除当前元素的不会影响到下一个元素的迭代器所以在调用erase之前记录下一个元素的迭代器即可。
3. 对于list来说它使用了不连续分配的内存并且它的erase方法也会返回下一个有效的iterator因此上面两种正确的方法都可以使用。

View File

@@ -38,3 +38,7 @@ foo_t *f = NULL;
### C++中的nullptr
* nullptr 关键字被自动转换为各种pointer类型。但他不会不转换为任何整型类型。防止null作为参数的时候出现函数重载的错误。
### 主要区别
* nullptr关键字nullptr是一种特殊类型的字面值它可以被转换成任意其它的指针类型而NULL一般被宏定义为0在遇到重载时可能会出现问题。

98
test.cpp Normal file
View File

@@ -0,0 +1,98 @@
#include <iostream>
#include <vector>
#include <map>
using namespace std;
struct ListNode{
ListNode(int a){
val = a;
}
ListNode* pre;
ListNode* next;
int val;
};
class Data{
public:
ListNode* head;
ListNode* end;
map<int,ListNode*> m;
int size;
Data(){
head = new ListNode(-1);
end = head;
size=0;
}
void set(int a){
ListNode* temp;
if(size==4){
temp = end;
end = end->pre;
m.erase(temp->val);
delete temp;
size--;
}
ListNode* n = new ListNode(a);
m[a]=n;
if(size==0){
head->next =n;
n->pre=head;
end = n;
size=1;
}
else{
temp = head->next;
head->next = n;
n->pre = head;
n->next = temp;
temp->pre = n;
size++;
}
}
ListNode* get(int a){
ListNode* temp = m[a];
if(temp==head->next){
return temp;
}
if(temp==end){
end = end->pre;
}
temp->pre->next = temp->next;
temp->next->pre = temp->pre;
ListNode* n = head->next;
temp->next = n;
n->pre = temp;
head->next = temp;
temp->pre = head;
return temp;
}
ListNode* get(){
return head->next;
}
~Data(){
ListNode* temp=head;
while(temp!=nullptr){
ListNode* n = temp;
delete n;
temp=temp->next;
}
}
};
int main() {
Data data;
data.set(1);
cout<<data.get()->val<<endl;
data.set(2);
data.set(3);
ListNode* temp = data.get(2);
cout<<temp->val<<endl;
temp = data.get();
cout<<temp->val<<endl;
cout << "Hello World!" << endl;
}

View File

@@ -0,0 +1,7 @@
## 协程
1. 最大的优势就是协程极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。
2. 第二大优势就是不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。
3. 因为协程是一个线程执行那怎么利用多核CPU呢最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。

View File

@@ -10,7 +10,13 @@
## 2 进程同步的原则与操作
1. 同步的原因两种制约关系
1. 直接制约关系
2. 简介制约关系
2. 同步的四大原则
1. 空闲让进
2. 忙着等待
3. 有限等待
4. 让权等待
3. 同步的实现方式
@@ -117,6 +123,18 @@
## 15 五种IO模型和epoll机制
调用顺序:
```
int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
```
1. 首先创建一个epoll对象
2. 然后使用epoll_ctl对这个对象进行操作把需要监控的描述添加进去这些描述如将会以epoll_event结构体的形式组成一颗红黑树
3. 接着阻塞在epoll_wait进入大循环当某个fd上有事件发生时内核将会把其对应的结构体放入到一个链表中返回有事件发生的链表。
## 16 终极三连问
1. 进程/线程的同步和通信原理、