背景 C语言中强制类型转换可以随意转换我们想要的类型,格式如下(类型)变量名,那么为什么C++还要引入新的4种类型转换呢? 1.新的类型转换控制符可以很好的控制类型转换的过程,允许控制各种类型不同的转换. 2.C++的类型转换控制服能告诉程序员或读者我们这个转换的目的是什么. static_cast< T * > (content): 静态转换(编译器处理) 它主要用于C++中内置的基本数据类型之间的转换, 但是没有运行时的检测来保证转换的安全性. 用于基类和子类之间的指针或引用的转换,这种转换把子类的指针或引用转换为基类表示是安全的.进行下行转换,把基类的指针或引用转换子类表示时,由于没有进行动态类型检测,所以是不安全的; 把void 类型的指针转换为目标类型的指针. 用于内置的基本的数据类型之间的转换. 把任何类型的表达式转换为void类型的 注意:static_cast不会转换掉content的const,volatile.__unaligned属性. const_cast< T*>(constent):去 继续阅读 >>


杨龙飞 17/02/13 11:34:16
什么是哈希表 1.哈希表又称为散列表,是根据关键码值(Key value)而直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中的一个位置来访问记录,以加快查找速度,这个映射函数叫做散列函数,存放记录的数组叫做散列表。  记录的存储位置=f(关键字) f是散列函数 这里的对应关系f称为散列函数,又称为哈希(Hash函数), 采用散列技术将记录存储在一块连续的存储空间,这块连续的存储空间称为散列表或哈希表(Hash table)。  2.哈希表hashtable(key,value)就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当做数组的下标,将value存储在以该数字为下标的数组空间里. 通过散列算法,变换成固定长度的输出,该输出就是散列值,这种是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值.简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数. 而当使用哈希表进行查询时,就是 继续阅读 >>


杨龙飞 17/02/10 21:07:12
1. 区别 new的功能是在堆区新建了一个对象,并返回该对象的指针,所谓的【新建对象】的意思就是,将调用该类的构造函数,因为如果不构造的话,就不能称之为一个对象。 malloc只是机械的分配了一块内存,如果用malloc在堆区创建一个对象的话,是不会调用构造函数的,严格来说malloc不能算是新建了一个对象,只能说是分配了一块与该类对象大小相同的内存而已,然后强行把它解释为【这是一个对象】,按这个逻辑来,也不存在构造函数什么事. 用delelte 去释放一个堆区的对象,会调用该对象的析构函数. 用free去释放一个堆区的对象,不会调用该对象的析构函数. 看一个例子 #include<iostream> #include <malloc.h> using namespace std; class TEST{ private: int num1; int num2; public: TEST(){ num1 = 10; num2 = 20; } ~TEST() 继续阅读 >>


杨龙飞 17/02/10 14:54:00
1.指针与引用区别 指针是一块内存的地址值,访问变量是间接访问,引用是一块内存的别名,访问变量是直接访问. 引用是一个变量的别名,本身不单独分配自己内存空间,而指针有自己的内存空间. 引用使用时无须解引用(*),指针需要解引用. 引用只能在定义时被初始化一次,之后不可变;指针可变. 引用不能为空,指针可以为空. “sizeof 引用”得到的是所引用的变量(对象)的大小,而”sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小. 指针和引用的自增(++)运算意义不一样. 引用是类型安全的,而指针不是(引用比指针多了类型检查) 2.指针与引用联系 引用的主要功能是传递函数的参数和返回值,c++语言中,函数的参数和返回值的传递方式有三种:值传递、指针传递、引用传递。 2.1引用的三种用法 (1)独立引用 #include<iostream> using namespace std; int main() { int a=3; int& b=a;//b与a绑定在一起,同 继续阅读 >>


杨龙飞 17/02/10 11:58:26
1.背景 RabbitMQ是一个由erlang开发的AMQP(Advanved Message Queue)的开源实现。 2.应用场景 2.1异步处理 场景说明:用户注册后,需要发注册邮件和注册短信,传统的做法有两种1.串行的方式;2.并行的方式 (1)串行方式:将注册信息写入数据库后,发送注册邮件,再发送注册短信,以上三个任务全部完成后才返回给客户端。 这有一个问题是,邮件,短信并不是必须的,它只是一个通知,而这种做法让客户端等待没有必要等待的东西. (2)并行方式:将注册信息写入数据库后,发送邮件的同时,发送短信,以上三个任务完成后,返回给客户端,并行的方式能提高处理的时间。 假设三个业务节点分别使用50ms,串行方式使用时间150ms,并行使用时间100ms。虽然并性已经提高的处理时间,但是,前面说过,邮件和短信对我正常的使用网站没有任何影响,客户端没有必要等着其发送完成才显示注册成功,英爱是写入数据库后就返回. (3)消息队列 引入消息队列后,把发送邮件,短信不是必须的业务逻辑异步处理 由此可以看出, 继续阅读 >>


杨龙飞 17/02/09 23:30:02
持续计时器 假设一种场景:A给B发送数据,如果B告诉A自己的缓冲区已满,于是A停止发送数据,等待一段时间后,B的缓冲区出现了富余,于是给A发送报文告诉rwnd大小为400,但是这个报文不幸丢失了,于是就出现A等待B的通知,B等待A发送数据的死锁状态,为了处理这种问题,TCP引入了持续计时器,当A收到B的零窗口通知时,就启用该计时器,时间到则发送一个字节的探测报文,对方会在此时回应自身的接收窗口大小,如果仍然为0,则重置持续计时器,继续等待. 重传计时器 当TCP发送报文段时,就创建该特定报文段的重传计时器,可能发-生两种情况: 若在计时器截止时间到之前收到了对此特定报文段的确认,则撤销此计时器. 若收到了对此特定报文段的确认之前计时器截止期到,则重传此报文段,并将计时器复位. 保活计时器 保活计时器使用在某些实现中,用来防止在两个TCP之间的连接出现长期的空闲,假定客户端打开了服务器的连接,传送了一些数据,然后就保持静默,也许这个客户端出故障了,在这种情况下,这个连接将永远保持打开状态,要解决这种问题,在大多数的实现中都是使服务器设置保活计时 继续阅读 >>


杨龙飞 17/02/09 09:27:02
和TCP三次同步握手不一样的是,TCP关闭连接用四次挥手来实现,即A—–>B Fin,B—->A ACK, B—–>A Fin,A—-B ACK A—-B Fin, B—->A ACK,A属于主动关闭方,收到B的ACK之后,A到B的方向连接关闭,即half shutdown,这时不能再发送数据了. 这种状态下B还是可以单向发送数据的,B的数据发送完毕,也可以做关闭动作了, B——>A Fin,A——> B ACK B收到ACK,关闭连接,但是A无法知道ACK是否已经到达B,于是开始等待?等待什么呢,假如ACK没有到达B,B会为FIN这个消息超时重传,那如果A等待时间足够,又收到FIN消息,说明ACK没有到达B,于是再发送ACK,知道在足够的时间内没有收到FIN,说明ACK成功到达,这个等待时间至少是:B的timeout+FIN的传输时间,为了保证可靠,采用更加保守的等待时间2MSL. MSL:报文段最大生存时间MSL.它是任何报文段被丢弃前网络内的最长时间。 TTL:IP对IP 数据报生存时间限制,255秒, 继续阅读 >>


杨龙飞 17/02/08 20:16:00
前言 本文将介绍常见的9种排序算法,围绕下面几个问题讨论每一种排序算法: 这个算法的思想是什么? 这个算法的稳定性怎样?时间复杂度是多少? 在什么情况下,算法出现最好情况or最坏情况? 这个算法的具体实现? 以下排序算法都以从小到大排序 1.冒泡排序(交换排序) 1.1算法思想: 排序每次对相邻的两个元素比较,如果它们的相对排列次序与所希望的不符,便交换它们的次序,这样,各元素就会像水中冒气泡一样通过交换它们的位置得到最终正确的位置.升序时,每次都把最大的元素放到n-i-1个元素的位置上,每次遍历的元素个数-1; 1.2 时间复杂度 最好的情况下:正序有序,则只需要比较n次,故为O(n) 最坏情况下:逆序有序,则需要比较(n-1)+(n-2)+…….+1,故为O(n*n) 1.3 稳定性 排序过程中只交换两个元素的位置,因此,当两个数相等时,是没有必要交换两个数的位置的,所以,它们相对位置并没有改变,冒泡算法是稳定的。 1.4代码实现 void BubbleSort(int a[],int n) / 继续阅读 >>


杨龙飞 17/02/08 12:46:38
 1.C++对象模型概述 有两个概念可以解释C++对象模型 1.语言中直接支持面向对象程序设计的部分 包括了构造函数、析构函数、多态、虚函数等等. 2.对于各种支持的底层实现机制 对象模型研究的是对象在存储上的空间与时间上的优化,并对C++面向对象技术加以支持,如以虚指针、虚表机制支持多态机制. 2.理解虚函数表 2.1多态与虚表 C++中虚函数的作用主要是为了实现多态机制,多台,简单的来说,是指在继承层次中,父类的指针可以具有多种形态——当它指向某个子类对象时,通过它能够调用子类的函数,而非父类的函数 class Base { virtual void print(void);} class Drive1:public Base{virtual void print(void);} class Drive2:public Base{vittual void print(void);} Base * ptr1 = new Base; Base *ptr2 = new Dri 继续阅读 >>


杨龙飞 17/02/05 11:19:48
__thread是GCC内置的线程局部存储设施,存取效率可以和全局变量相比.__thread变量每一个线程有一份独立实体,各个线程的值互不干扰,可以用来修饰那些带有全局性且值可以变,但是又不值的用全局变量保护的变量. __thread使用规则:只能修饰POD类型(类似整型指针的标量,不带自定义的构造、拷贝、赋值、析构的类型,二进制内容可以任意复制memset,memcpy,且内容可以复原),不能修饰class类型,因为无法自动调用构造函数和析构函数,可以用于修饰全局变量,函数内的静态变量,不能修饰函数的局部变量或者class的普通成员变量,且__thread变量值只能初始化为编译器常量(值在编译器就可以确定const int i=5,运行期常量是运行初始化后不再改变const int i=rand()). #include<iostream> #include<pthread.h> #include<unistd.h> static int var = 5; //__thread int var = 5; //用 继续阅读 >>


杨龙飞 17/01/03 15:34:18