非凸上海(实习)-- 一面
结果:一面过了,但是由于个人原因不能参加二面。
体验:面试官水平高,收获很多。
- 自我介绍
- 介绍实习内容(部门背景、仿真)
- 拷打实习内容:为什么不用lru进行优化(lru开销过高,得不偿失)、优化效果只有60分之1(简历写错了,十分之一)?
- 拷打项目:
- 协程异步库:
- 协程与线程区别?(先说了进程与线程,进程就是切换开销大,需要保存的上下文多。协程与线程的关系类似于线程和进程)(不满意,回去恶补)
- 协程比线程的优点?(切换开销低,线程切换是需要进入内核,协程是在内核态完成。协程的栈比线程小。。。。)
- 协程的栈比线程小的好处和坏处?(好处:同样的环境可创建更多的任务,并行、并发数更高。坏处:就是栈小,函数调用层次会变小,套娃次数变小,容易爆栈)
- 怎么解决坏处?(协程分有栈和无栈:有栈的需要创建时申请并指定栈空间,解决就是把这个空间预申请大一点,无栈(c++20)的不懂。)(msg:无栈的不会导致爆栈,但是会有别的坏处,建议真想学去看看boost库的fiber,有栈)(c++20协程是通过堆空间管理)
- 拷打简历:
- “避免锁和线程切换,是指库的用户不用创建,还是说本身框架就不用创建?”(都不用,框架本身就是单线程的)
- “单线程不就无法利用多核了吗?”(是的,如果要,就创建多个线程,各自独立的运行事件循环)
- “那你这样做,同一个协程可以放到不同的线程执行吗?”(不行)(那这样不太可用)
- “异步io,网络异步io听过,文件异步io没听过,先说一下网络异步io”(一个链接的socket fd,如果需要读写,co_await, 将fd加入到eventloop监听,同时协程挂起,当fd可读时,重新将挂起的协程加入调度)(至于文件异步io,msg说没有,我自己也说不清除)
- muduo:
- 项目中多线程场景?怎么避免线程竞争数据?(场景:多个线程从任务队列取任务,任务是用std::function<void()>封装,同步就用mutex, condition_variable)
- std::function<void()>封装任务时会申请动态内存吗?(不懂,只会用,没有深究原理)(后补:会的,有点类似于lambda表达式一样,std::funciton是一个模板类,根据传入的返回类型以及参数类型去重载调用运算符,模范类在调用时就会实例化一个类和对象。实例化时机是在编译期间。)
- 怎么管理动态内存?(delete和new要一一对应;RAII:构造申请资源,析构释放资源;智能指针(shared、weak、unique))
- 说一下shared_ptr和unique_ptr区别?(shared_ptr运训拷贝以及赋值,说了一下引用计数的变化,以及内存释放时机;而unique_ptr只允许移动构造以及移动赋值,借助std::move)
- 右值和右值引用?(说了一下移动语义,右值:没有地址,比如一个常量数字123,追问:还有呢,不懂,右值引用,不懂)。(后补:右值:没有变量名、没有地址,表达式结束后就不再存在的临时对象。常见右值:字面量(除字符串)、临时表达式的值、临时函数的返回值。右值又分为将亡值(类型为右值引用类型的返回值)和纯右值(单纯的临时值))
- 八股:
- 常见容器的迭代器失效情况:
- vector:元素满的时候,需要重新申请空间,将元素从原来的地方搬到新申请的空间,而迭代器其实就是对int*做了一下封装,此时迭代器就会失效,(追问,刚刚说的就是只有push_back,还有没有其他情况)其他失效情况就是插入insert、删除erase。
- map:(回答错误:说了底层是红黑树,插入和删除都会导致树的结构变化,说了插入删除到会导致迭代器失效。)msg:指针还是指向那个节点(改口:对的,只有那个节点失效)
- unordered_map: (底层哈希表实现,当元素过多,超过负载因子,就会需要重新申请更大的空间,把就的元素,重新hash到新的hash桶,此时迭代器会失效)(???除此之外,插入和删除会不会导致失效啊????)(后补:除rehash外,删除和增加不会导致迭代器失效,对已经节点除外)
后补:迭代器失效情况;https://blog.csdn.net/xp178171640/article/details/104905338
- 手撕:ip转数字(其实‘’12.34.56.78“这个ip,系统中是用一个uint32_t来存储,现在就是从字符串求这个整数)
题目只保证字符串有数字和点,不保证ip合法性
大概就是左右指针找出点与点之间的数字tmp, 遇到第一个点之前:ret += tmp << 24 遇到第二个点之前:ret += tmp << 16 遇到第三个点之前:ret += tmp << 8 不合法ip: ..... 1.2.3. 277.2.2.1 0.0.0.0 1..2.1 1.2.1 (考虑到了)点必须要有三个,不多不少, (考虑到了)点与点之间是有数字的(反例1..2.3) (考虑到了)结尾的边界,只有点没有数字(1.2.3.) (没考虑)点与点之间的数字大于255(266.266.1.1) 优化: 字符串转数字,我一开始用的是istringstream(字=子串),后面用stod(子串),再后面自己实现字符串转数字(基于原有字符串)