今天做的事还蛮多的,从c++的移动语义,就是右值拷贝和赋值运算符再到RAII(用栈的生命周期来管理类对象,在该类的构造函数中初始化要管理的堆空间变量的指针,在析构函数中delete堆空间,从而达到自动释放的效果)引出三种智能指针unique_ptr,shared_ptr,weakptr,
再到c++虚函数的设置,例如构造函数不能设置为虚函数,因为虚函数表是专属于一个类的表,在编译的时候就已经创建好,而调用这个虚函数表,需要虚函数指针,虚函数指针是在对象创建过程中被创建分配到对象的内存空间上。如果将构造函数设置为虚函数,必须要到虚函数表中找到这个构造函数,才能创建对象。而要访问虚函数表又需要虚函数指针,然而虚函数指针需要对象创建后才分配,闭环了,所以构造函数不能设置为虚函数。且只有类内成员函数才能被设置为虚函数,静态成员函数也不能被设置为虚函数。
又到单例模式,把之前不想学的饿汉式和懒汉式细细的看了一遍。发现饿汉式就是直接将静态成员变量用new创建对象来初始化,懒汉式是用到了才去初始化。至于懒汉式的加锁我想面试官应该不会问那么细吧,就又懒得看了,原理大致了解了一下。
c++11的新特性,范围for循环,auto,智能指针,移动语义,bind和function用于回调。Lamba,线程库之类的。
select的缺陷,首先需要创建一个数组fd_set副本用于select的修改,而且调用select会把该数组从用户态拷贝到内核态,这是缺陷一。缺陷二,需要遍历这个数组然后对其修改,将注册的就绪事件的那一位设置为1。返回就绪事件的个数,但是却不知到是哪个就绪还需要遍历一遍这个数组后去就绪事件这是缺陷二。缺陷三只有1024位,导致无法实现多用户监听。
poll也只有再1024的基础上做了改进,从原先的位数组到链表而已,其它的缺陷仍然没有避免;
epoll则完全避免了用户态到内核态的拷贝已经遍历这个繁琐的流程。首先有两个数据结构,一个是红黑树,专门管理用来监听的文件描述符,另外一个是链表,用来存储这个文件描述符的事件信息。当向红黑树中注册文件描述符时,会和网卡设定回调关系,即检测到该文件描述符就绪就会将文件描述符对应的事件添加到链表中。epoll_wait遍历这个链表返回的是就绪事件的个数。
过度完网络编程很快又来到了STL,当然绕不开经典的vector,deque以及list,动态数组和双向链表就不必说了,deque确实有点经典,其中使用一个中控器来管理每个缓存区,每个缓存区又有一个迭代器负责管理(控制该缓存区到下一个缓存区的跳跃,当检测到cur = finish的时候,中控器就会右移到下一个指针(管理新的缓存区)),也就将分散的缓存队列再逻辑上合并了一个整体。确实经典。
有复习了一些,new和malloc的区别,只记了两个应该够用一个new能返回有类型的指针,但malloc只能返回void*,另一个是new能调用构造函数,创建对象,例如再堆上创建对象以及delete调用析构函数,说到析构函数,它是可以也必须要当作虚函数的,如果用基类指针指向派生类对象,不设置虚函数就无法事件派生类的析构函数的覆盖,调用派生类的析构函数进而能调用基类的析构函数不会出现内存泄漏的情况。
静态链接库和动态链接库的区别,一个是在编译时链接,即把代码直接写到自己实现的函数中,另一个是在运行时编译把只调用接口。
锁的底层实现,其实相当简单,就是再做修改操作之前,拷贝一个值,然后对其进行修改,修改完之后再取出内存的值看和快照保留的值是否一致,一致则将其刷新内存中。
后面又看了一下代码随想录的双指针,还是从中学到了一些东西的,就比如快慢指针,二次翻转,二叉树的前中后序遍历,递归的方式,还有迭代的方式,目前掌握的只有前序只要用一个队列就能实现,相当简单。快排也是很简单,就实现两个功能一个找基准,从基准的相反位置进行遍历,把大于基准的值移动到相反位置的第一位,不变,最后将基准移动到对应位置,调用递归进行左右处理即可。
今天大致就学了这么多东西,广州这边的工作大致两个方向,一个方向是游戏服务器,需要学习lua和skynet还有一个就是除了游戏服务器的别的方向,打算学lua和skynet后再更新简历投一下,不行的话只能去深圳了。之前做的两个服务器开发以及搜索引擎的项目又过了一遍,代码能力还保持在手搓线程池的手感,打算多写一点算法题来温润手感。最后今天要把进程通信和线程通信搞一下,这个不能靠文字了,需要写代码感受一下。还有就是看一下lua和skynet的网课,加油,明天会更好。