前言 C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议。 关于虚函数的使用方法,我在这里不做过多的阐述。大家可以看看相关的C++的书籍。在这篇文章中,我只想从虚函数的实现机制上面为大家 一个清晰的剖析。 当然,相同的文章在网上也出现过一些了,但我总感觉这些文章不是很容易阅读,大段大段的代码,没有图片,没有详细的说明,没有比较,没有举一反三。不利于学习和阅读,所以这是我想写下这篇文章的原因。也希望大家多给我提意见。 言归正传,让我们一起进入虚函数的世界。 虚函数表 对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的 继续阅读 >>


楚东方 18/04/24 11:59:24
Libfly协程库实现与原理——协程的优点与用处 为什么写一个协程库?协程有什么优点?这些问题非常重要,在做一件事情前需要一个做他的最初动力对吧。 我们先说一个普通的server模式 reactor: 这里有一个半同步/半异步模式的多线程结构,主线程监听socket,把相应的事件放入请求队列,然后工作线程进行在队列中取出事件,并执行相应的I/O。 现在问题来了,这样的模式有没有CPU浪费那? 显然是有的 1. epoll_wait(100ms),epoll等待事件该线程会阻塞,占用一个CPU核 2. 线程间切换以及锁的争用的浪费CPU 想一下如果是一个8核的CPU,1个核用于epoll_wait(),7个核是用于工作线程,在当一个事件来临时,要通过条件变量,互斥锁,唤醒工作线程。这个过程是通过内核线程调度来实现的,但一定不会是最优的。因为你不知道内核是怎么调度的,优先级是什么,你也无法直接操作唤醒某个线程。 那么现在我不想通过内核来调度了,我觉得它太浪费时间,不如我自己 继续阅读 >>


楚东方 18/03/17 00:36:39
新建一个专门用于 EventLoop 的线程 实现:启动一个线程,在其中运行 EventLoop::loop() 功能:运行Evenloop 知识点 条件变量使用:当多个线程对同一个变量进行操作时使用条件变量对其进行保护,条件变量同互斥锁一同起作用。 代码及分析: EventLoopThread.h // Copyright 2010, Shuo Chen. All rights reserved. // http://code.google.com/p/muduo/ // // Use of this source code is governed by a BSD-style license // that can be found in the License file. // Author: Shuo Chen (chenshuo at chenshuo dot com) #include <muduo/net/EventLoop 继续阅读 >>


楚东方 18/03/11 21:35:14
缓冲区(非阻塞 IO 必备) 实现:实现Buffer类 功能:缓冲区,为非阻塞IO暂时存储数据,实现高效IO 知识点: string的函数实现 resize() Resizes the string content to n characters. If n is smaller than the current length of the string, the content is reduced to its first n characters, the rest being dropped. If n is greater than the current length of the string, the content is expanded by appending as many instances of the c character as needed to reach a size of n characters. The second 继续阅读 >>


楚东方 18/03/11 19:22:10
二叉搜索树的定义 二叉搜索树,也称有序二叉树,排序二叉树,是指一棵空树或者具有下列性质的二叉树: 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 任意节点的左、右子树也分别为二叉查找树。 没有键值相等的节点。 二叉搜索数中序遍历为有序数组 一、查找二叉搜索树中的某个元素 在二叉搜索树b中查找x的过程为: 若b是空树,则搜索失败,否则: 若x等于b的根节点的数据域之值,则查找成功;否则: 若x小于b的根节点的数据域之值,则搜索左子树;否则: 查找右子树。 二、从有序数组构造一个二叉搜索树 三、往二叉搜索树中插入元素 向一个二叉搜索树b中插入一个节点s的算法,过程为: 若b是空树,则将s所指结点作为根节点插入,否则: 若s->data等于b的根节点的数据域之值,则返回,否则: 若s->data小于b的根节点的数据域之值,则把s所指节点 继续阅读 >>


楚东方 18/03/05 16:35:10
buddy system简介: buddy system内存管理,努力让内存分配与相邻内存合并能快速进行(对于普通算法来讲,合并内存相当困难),它利用的是计算机擅长处理2的幂运算。 我们创建一系列空闲块列表,每一种都是2的倍数。 举个例子,如果最小分配单元是8字节,整个内存空间有1M。我们创建8字节内存块链表,16字节内存块链表,32字节内存块链表,64,128,256,512,1k,2K, 4K, 8K, 16K, 32K, 64K, 128K, 256K, 512K 和一个1M内存块链表。 除了1M内存块链表有一个可用单元,其余链表初始为空。所有的内存分配都会向上取整到2的倍数—-70K会向上取整到128K,15K会向上取整到16K,等等。 什么是Buddy buddy system允许一个被分配块单元平均拆分成两个大小是原来一半的块单元,这两个块单元互为伙伴。块B的伙伴必须满足大小跟块B一样大,并且内存地址相邻(才可以合并)。 另一个伙伴性质是所有块单元在内存中的地址必须能被它自 继续阅读 >>


楚东方 18/03/03 22:58:13
Libfly协程库简介: libfly协程库,采用C++作为编程语言,封装了协程类,并提供了协程基本操作和调度功能 编写此协程库的目的是为了让协程理解起来更容易,让协程编程更加简单! 正逐步完善代码注释与文档,欢迎大家一起讨论交流~ Github地址:https://github.com/chudongfang/libfly libfly协程库条件变量的实现 因为协程不会同时运行,所以不需要互斥锁,只需要条件变量 条件变量封装在 Conditional_variable 类中 wait() 函数等待条件变量 notify_one 唤醒一个等待协程 notify_all 唤醒所有等待协程 实现原理 其实现难点为如何唤醒协程, 这里我采用定时器,利用定时器的回调唤醒协程 这样一来 notify_one 和 notify_all 就可以轻松实现了 然后wait函数只需负责构造一个定时事件,存储需要唤醒的协程就好了 这个定时事件的时间需要非常短,这里我给了1秒. cl 继续阅读 >>


楚东方 18/02/25 22:29:04
Libfly协程库简介: libfly协程库,采用C++作为编程语言,封装了协程类,并提供了协程基本操作和调度功能 编写此协程库的目的是为了让协程理解起来更容易,让协程编程更加简单! 正逐步完善代码注释与文档,欢迎大家一起讨论交流~ Github地址:https://github.com/chudongfang/libfly 一、协程的实现 与线程类似一个协程包括以下三个方面: (1) 有一段程序供其执行,不同的协程可以共用同一段程序。 (2) 与线程一样,协程有专属的系统堆栈空间。 (3) 一个存储协程相关信息的协程控制块,这里我把其封装在一个协程类中。 协程类 先来看一下协程类,其描述了一个协程,包含了协程的所有信息。 //协程块 class Routine { public: Routine(RoutineEnv * env,const RoutineAttr* attr ,void*(*pfn)(void*),void *arg ); ~R 继续阅读 >>


楚东方 18/02/25 20:39:18
LT 电平触发 高电平触发 EPOLLIN 事件 数据可读 内核中的socket接收缓冲区 为空 低电平 不会触发 内核中的socket接收缓冲区 不为空 高电平 会触发 EPOLLOUT事件 数据可写 内核中的socket发送缓冲区不满 高电平 内核中的socket发送缓冲区 满 低电平 ET 边沿触发 转换的时候触发 由低电平 -> 高电平 才会 触发 高电平 -> 低电平 触发 下面代码是LT和ET模式的区别 #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <unistd.h> #include <errno. 继续阅读 >>


楚东方 18/02/07 14:59:10
使用boost库时,经常会看到如下的类 class A:public enable_share_from_this 在什么情况下要使类A继承enable_share_from_this? 使用场合:当类A被share_ptr管理,且在类A的成员函数里需要把当前类对象作为参数传给其他函数时,就需要传递一个指向自身的share_ptr。 我们就使类A继承enable_share_from_this,然后通过其成员函数share_from_this()返回当指向自身的share_ptr。 以上有2个疑惑: 1.把当前类对象作为参数传给其他函数时,为什么要传递share_ptr呢?直接传递this指针不可以吗? 一个裸指针传递给调用者,谁也不知道调用者会干什么?假如调用者delete了该对象,而share_tr此时还指向该对象。 2.这样传递share_ptr可以吗?share_ptr 这样会造成2个非共享的share_ptr指向一个对象,最后造成2次析构该对象。 boost官方文档中一个非 继续阅读 >>


楚东方 18/02/07 01:18:14