
C++
文章平均质量分 75
vincent-xia
这个作者很懒,什么都没留下…
展开
-
C++ 引用计数
C++没有像java那样的垃圾回收机制,但是我们可以实现一个。一种很简单的方式就是使用引用计数。它实际上是一种用对象来管理资源的方式,因为普通的栈上的对象在离开作用域时会调用对应的析构函数,根据这个特性,可以实现用于对指针进行管理的类。下面以一个对int*指针的管理来说明引用计数是如何实现的。当我们创建一个int型指针时:int *p=new int(10);在最后我们需要调用dele原创 2015-10-21 11:04:32 · 8381 阅读 · 0 评论 -
socket通信之九:使用完成端口实现的一个聊天室
基本上windows平台下的几种IO模型都实现了一遍,还有两个没有实现,但是它们一个需要基于windows消息,一个和重叠IO中的事件通知模型比较类似,并且不能实现真正的异步,所以就不列出来了。这一篇介绍如何实现一个聊天室。前面介绍的几种模型中除了基本的socket模型和阻塞版本的模型之外都可以用来实现聊天室,因为这两个模型还不能实现支持多个客户端。对于其它的几个模型,我们需要做的只是原创 2015-09-04 23:08:02 · 4737 阅读 · 1 评论 -
socket通信之八:完成端口模型实现的客户/服务器模型
完成端口的详细说明可以参考下面这两篇文章,理论讲的很好。手把手教你玩转SOCKET模型:完成端口(Completion Port)详解 完成端口(I/O completion)原理 收藏但是本文的实现和它们还是有点区别。这里就只列出完成端口服务器端的基本流程了。首先,说说主线程:1.创建完成端口对象2.创建工作者线程(这里工作者线程的原创 2015-09-03 16:10:38 · 2472 阅读 · 0 评论 -
socket通信之七:Overlapped I/O 完成例程模型实现的客户/服务器模型
前一篇介绍了重叠IO的一种实现方式即基于事件通知的方式,这一篇介绍另外一种方式,即使用完成例程的方式实现重叠IO,首先声明这种方式比事件通知的方式简单多了。用完成例程来实现重叠I/O比用事件通知简单得多。在这个模型中,主线程只用不停的接受连接即可;辅助线程判断有没有新的客户端连接被建立,如果有,就为那个客户端套接字激活一个异步的WSARecv操作,然后调用SleepEx使线程处于一种可原创 2015-09-03 14:00:24 · 2304 阅读 · 0 评论 -
socket通信之六:Overlapped I/O 事件通知模型实现的客户/服务器模型
1.基于事件通知模型的Overlapped I/O(重叠IO模型)概括一点说,重叠模型是让应用程序使用重叠数据结构(WSAOVERLAPPED),一次投递一个或多个Winsock I/O请求。针对这些提交的请求,在它们完成之后,应用程序会收到通知,于是就可以通过自己另外的代码来处理这些数据了。 需要注意的是,有两个方法可以用来管理重叠IO请求的完成情况(就是说接到原创 2015-09-02 21:12:42 · 3437 阅读 · 0 评论 -
socket通信之五:select多路复用的客户/服务器模型
前面一篇介绍了服务器端使用多线程的方式来处理多个客户端的请求的,但是当客户端数量增多时线程数量会急剧增加,导致消耗大量的资源。于是就引出了服务器端的一种新的模型。1. 阻塞与非阻塞首先介绍几个基本的概念。阻塞方式( block ),顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件的发生,假如事件没有发生,进程或线程就被阻塞,函数不能立即原创 2015-09-02 14:52:47 · 5797 阅读 · 3 评论 -
socket通信之四:多线程版本的客户/服务器模型
上一篇中阻塞版本的客户/服务器模型实现了一个客户端能连续向服务器端发送数据,但是因为服务器端在循环体内会被阻塞,这样其它客户端再连接服务器端时服务器是无法处理的,这就导致了服务器只能处理一个客户端,其它客户端都会等待,直到当前处理的客户端退出,然后就会再有一个客户端和服务器端连接。这一篇文章介绍一种可以让多个客户端同时能和服务器端通信的方式,就是服务器端的多线程模型,服务器每次调用accept建立一个连接后,启动一个新的线程为这个连接服务,然后服务器继续执行,这样就不会陷入阻塞状态了。原创 2015-09-02 14:51:52 · 2739 阅读 · 2 评论 -
socke通信之三:阻塞版本的客户/服务器模型
上一篇中实现出来的客户端只能向服务器端发送一次数据,然后就断开了连接,那么如果需要向服务器端持续发送数据,那么应该怎么做? 一个很直观地想法就是修改客户端的第4步,即发送,接收数据那一步,在基本的客户/服务器模型中我们是直接发送一个字符串给服务器端,现在我们从控制台接收数据将接收到的数据发送给服务器端,然后从服务端端接收数据并打印输出。并持续从控制台读取数据。原创 2015-09-02 14:50:30 · 1150 阅读 · 0 评论 -
socket通信之二:实现一个基本的客户/服务器模型
前一篇介绍了TCP/IP协议族和socket的一些基本的知识,这篇文章介绍在windows下如何实现一个使用socket通信的客户和服务器模型。首先还是将基本的流程回顾一下,任何复杂的模型都是从这个基本的模型中衍生出来的,然后介绍一下在windows平台下相关的api。服务器端编程的步骤:加载套接字库,创建套接字(WSAStartup()/socket())原创 2015-09-02 14:48:06 · 4513 阅读 · 1 评论 -
socket通信之一:TCP/IP模型与socket
这段时间看了一些网络相关的东西,这里做一个总结吧。参考了很多文章的内容,因为我本身是对着书并且参考网络资源在学习的,在最后会一一列出文章的地址。这篇文章主要介绍TCP/IP的一些基本知识,后面几篇继续深入一点探究。本篇主要包括下面这些知识:TCP/IP是什么socket介绍socket通信流程socket中TCP三次握手建立连接socket中TCP的四次挥手释放连接原创 2015-09-02 14:44:28 · 8239 阅读 · 0 评论 -
定义一个只能在栈上构造对象的类
只能在堆上定义的对象可以通过声明构造函数是私有的,然后提供两个静态的方法,一个方法用来获取堆上的对象,一个用来释放堆上的对象。C++中定义一个不能被继承的类中第二种方法就是通过这种方式声明了一个不能被继承的类,但是这个类的对象就只能位于堆中了。那么如何一定一个只能在栈上构造的对象?这个就涉及到了C++中new这个操作符,它包含两步:调用一个全局的operator new函数原创 2015-08-31 16:33:18 · 1595 阅读 · 0 评论 -
火车进站问题
描述给定一个正整数N代表火车数量,0知识点栈运行时间限制0M内存限制0输入有多组测试用例,每一组第一行输入一个正整数N(0输出输出以字典序排序的火车出站序列号,每个编号以空格隔开,每个输出序列换行,具体见sample。样例输入3原创 2015-08-31 15:20:31 · 3512 阅读 · 0 评论 -
C++中定义一个不能被继承的类
一种错误的解法最开始是从构造函数开始着手(先声明这种方法不能定义一个不能被继承的类,这是一种错误的方法,但是很容易往这方面想),假设存在下面的继承体系:现在假设B是一个不能被继承的类,那么如果存在B的子类C,那么C的构造过程应该会报错,那么如何能够让B能正常构造而C不能正常构造呢?首先A,B,C的构造函数和析构函数都假设是public的,最开始想的是让B私有继承自A,根据priva原创 2015-08-31 10:56:16 · 9000 阅读 · 2 评论 -
二叉树遍历的应用(路径和问题,判断是否是二叉搜索树,判断是否是二叉平衡树)
现在越发觉得关于树的问题真是千变万化,随便改一个条件又会是一个新的问题。问题:一棵二叉树每个节点包含一个整数,请设计一个算法输出所有满足条件的路径:此路径上所有节点之和等于给定值。注意此类路径不要求必须从根节点开始。如果没有最后一个条件,这道题在leetcode上面过,就是采取先序遍历的方式并记录下路径。但是加上最后一个条件后需要转下弯思考一下。当然也需要记录下原创 2015-08-25 20:53:22 · 1740 阅读 · 0 评论 -
文件扩展名批量修改器
之前在使用SourceInsight查看一些开源项目的源代码时发现了一个很重要的问题,就是有些开源的工程的头文件现在都没有.h的后缀名了。编译器可以包含这些没有扩展名的头文件,但是使用SourceInsight打开这些工程时却没办法包含这些头文件,或者说即使包含了这些头文件在SourceInsight中查看源码时要找到某个类的声明更本找不到,不知道这算不算SourceInsight的一个bug。原创 2015-08-21 19:26:21 · 1542 阅读 · 0 评论 -
使用逆波兰式进行表达式求值
中缀表达式及后缀表达式图解中说明了使用逆波兰式进行表达式求值的方法,这里使用C++进行实现。实现和原理讲解有一点不同,需要进一步进行细化。关于将中缀表达式转换成后后缀表达式的规则:规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于找顶符号(乘除优先加减)则栈顶元素依次出找并输出,并将当前符号进栈原创 2015-08-13 23:12:39 · 5951 阅读 · 1 评论 -
中缀表达式及后缀表达式图解
平常我们见到的四则运算表达式都是中缀表达式,这种表示方法适合人阅读,但是不适合计算机计算,因为乘除号出现在加减号的后面时可能要先计算后面的加减号,加上括号后就更加麻烦了。计算机可以通过逆波兰式来非常方便的实现计算。计算机实现四则运算主要分两步进行:将给定的中缀形式的表达式转换成后缀表达式形式利用后缀表达式执行计算下面是上面两个步骤的图解过程(这实际上是《大话数据结构》一书中的图转载 2015-08-13 22:34:58 · 8554 阅读 · 0 评论 -
堆和栈
转载自:http://blog.youkuaiyun.com/goingup/article/details/618309堆和栈究竟有什么区别? 主要的区别由以下几点: 1、管理方式不同; 2、空间大小不同; 3、能否产生碎片不同; 4、生长方向不同; 5、分配方式不同; 6、分配效率不同; 管理方式:对于栈来讲,是由编译器转载 2015-08-12 19:39:33 · 530 阅读 · 0 评论 -
关于C++内存中字节对齐问题的详细介绍
转载自:http://m.jb51.net/article/36903.htm本篇文章是对C++内存中字节对齐的问题进行了详细的分析与总结。需要的朋友参考下一、什么是字节对齐计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定转载 2015-07-13 22:52:50 · 650 阅读 · 0 评论 -
string对象操作
标准string对象支持长度可变的字符串操作。使用它需要包含头文件,它位于std命名空间下。1.string对象的定义和初始化string s1; //默认构造函数,s1为空串string s2(s1); //将s2初始为s1的一个副本string s3("value"); //将s3初始为一个字符串字面值的副本string s4(n,'c'); //将s4初始为字符串'c'的n个副本需要注意原创 2015-06-11 13:26:37 · 802 阅读 · 0 评论 -
switch匹配问题
C和C++中的switch匹配case的问题,记住下面2条原则就行了:只有当所有case都不匹配时才会进入default语句当找到一个匹配(无论是case还是default)后,会进入下面的case语句,直到找到break才会跳出switch。 我们把一个正常的switch的default语句转移到代码的最开始处然后执行代码可以发现问题:#include <stdlib.h>#inc原创 2015-05-31 13:22:44 · 3414 阅读 · 0 评论 -
类成员变量中存在引用,const,和指针类型时需要注意的事项
背景知识编译器默认生成函数的规则如下:1.定义一个类时,如果自己没有声明,那么编译器会自动帮助生成一个拷贝构造函数(copy construction),赋值操作符(copy assignment),析构函数(deconstruction)。2.如果没有声明任何构造函数(包括拷贝构造函数),编译器会帮助声明一个默认构造函数。构造函数(包括编译器生成的默认构造函数)的执行包括两个阶段原创 2015-05-24 15:06:13 · 3107 阅读 · 0 评论 -
C++中的public,protected,private继承
转载自:http://blog.youkuaiyun.com/fingding/article/details/6799913http://blog.sina.com.cn/s/blog_60cc33d70100xylq.html一览大观先贴张图:1. public继承 从语义角度上来说,public继承是一种接口继承(可以理解为子类对象可以调用父类的接口,也转载 2015-05-23 14:46:06 · 816 阅读 · 0 评论 -
const,enum,inline替换#define
基本上使用预处理指令#define的地方都可以使用const,enum或者inline来替换掉它。主要的原因有两个:#define ASPECT_RATIO 1.6531.预处理指令是在编译前就进行预处理的(gcc -E进行预处理,它的输出文件作为gcc -S进行编译的输入),所以编译器是看不到#define定义的符号ASPECT_RATIO ,故它不会出现在符号表中,这样如果编译期间出现原创 2015-05-21 16:59:47 · 997 阅读 · 0 评论 -
继承中虚函数的缺省参数值问题
如果类继承中重新定义了虚函数,那么虚函数中的缺省参数不要重新定义。用一句话来解释原因就是:虚函数是动态绑定的(dynamically bound),但是缺省参数却是静态绑定的(statically bound)。静态类型和动态类型首先需要了解什么是对象的静态类型和动态类型,对象的所谓静态类型(static type),就是它在程序中被声明时所采用的类型。以下面的类为例:clas原创 2015-05-20 16:40:05 · 2486 阅读 · 0 评论 -
int **指针问题
在打印二维数组时遇到了问题,二维数组可以这样定义int matrix[ROWS][COLUMNS],但是打印二维数组时函数的声明是void printMatrix(int ** numbers,int rows,int columns)。那么将matrix作为参数传递给printMatrix时会出现问题,因为matrix是 int (*)[COLUMNS]类型的,但是函数printMatrix需要原创 2015-04-30 16:40:43 · 7817 阅读 · 2 评论 -
模板函数的定义和声明须在同一文件内
转自:http://www.360doc.com/content/11/1129/21/1030755_168473920.shtml#按照C++中代码的惯例,类声明在h文件中,类定义在cpp文件中,相应的成员函数声明也在h文件中,定义在cpp文件中。但是如果这样的架构用在模板函数中,在调用模板函数的地方链接器便会报错,error LNK2001: unresolved external sy转载 2015-04-29 16:46:53 · 759 阅读 · 0 评论 -
8中常见的排序算法
#include #include #include //冒泡排序void boblesort(int * arr,int n);//插入排序void insertsort2(int *arr,int n);//希尔排序void shellsort2(int *arr,int n);//选择排序void selectsort(int *arr,int n);//归并排序v原创 2015-03-24 17:09:40 · 1203 阅读 · 0 评论 -
函数调用中的堆栈平衡
转载自:http://www.cnblogs.com/ajiannet/archive/2007/04/20/721679.html[汇编学习]献给汇编初学者-函数调用堆栈变化分析(转自黑客风云)跟一个朋友谈堆栈的时候 就写下了这段文字,顺便发到这里给需要的看看吧汇编初学者比较头痛的一个问题////////////////////////////////////////转载 2015-03-13 15:43:20 · 1108 阅读 · 0 评论 -
C++中浮点数在内存中的表示
复制了两篇文章的内容:http://blog.youkuaiyun.com/nethibernate/article/details/6120382http://www.cnblogs.com/dolphin0520/archive/2011/10/02/2198280.html也是由一道题目引出的问题:#include int main(){ printf("%f\n"转载 2015-03-11 17:04:34 · 2112 阅读 · 2 评论 -
C++中模板类的友元重载
一个由《程序员面试宝典》引出的问题。描述模板类的友元重载,用C++代码实现?这实际上考察的是下面几个问题:1.模板类的编写2.模板类中友元函数的编写3.什么时候会用到友元重载?答案是各种C++中的运算符。最典型的就是输出操作符书上给出的答案如下:#include using namespace std;template class Test;template原创 2015-03-10 16:41:00 · 3420 阅读 · 1 评论 -
C++ 初始化列表
C++ 初始化列表何谓初始化列表与其他函数不同,构造函数除了有名字,参数列表和函数体之外,还可以有初始化列表,初始化列表以冒号开头,后跟一系列以逗号分隔的初始化字段。在C++中,struct和class的唯一区别是默认的访问性不同,而这里我们不考虑访问性的问题,所以下面的代码都以struct来演示。struct foo{ string name ; i转载 2015-03-09 21:32:30 · 480 阅读 · 0 评论 -
C++中构造函数,拷贝构造函数,析构函数
C++中默认构造函数就是没有形参的构造函数。准确的说法,按照《C++ Primer》中定义:只要定义一个对象时没有提供初始化式,就是用默认构造函数。为所有 的形参提供默认实参的构造函数也定义了默认构造函数。合成的默认构造函数,即编译器自动生成的默认构造函数。《C++ Primer》中的说明:一个类哪怕只定义了一个构造函数,编译器也不会再生成默认构造函数。这条规则的根据是,如果一个类再某种情况下原创 2015-03-09 21:29:30 · 4311 阅读 · 0 评论 -
C++中成员变量加上static或const关键字后的分析
C++中类成员变量加上static或const关键字后的初始化问题。在一个简单的C++类中定义如下这些变量:#include using namespace std;class TestVariable{ public: TestVariable(){} private: int intVariable;//情况0 不加限定符,这个不需要进行讨论 const int cons原创 2015-03-09 11:15:11 · 3375 阅读 · 0 评论 -
stl中push_back和浅拷贝和深拷贝的问题
《程序员面试宝典》中stl模板与容器中的一个例子:#include #include #include #include #include using namespace std;class CDemo{ public: CDemo():str(NULL){}; ~CDemo(){ if(str) delete[] str; }; char * str原创 2015-03-08 23:03:39 · 33026 阅读 · 1 评论 -
指针和数组参数
作为函数参数的数组名和指针是相等的。之所以要把传递给函数的数组参数转换为指针是出于效率的考虑。在c语言中,所有非数组形式的数据实参均以传值形式调用。然而,不过拷贝整个数组,无论在时间还是在内存上的开销都有可能非常大。而且绝大部分情况下,你其实并不需要整个数组的拷贝,你只想告诉函数在那一时刻对那个特定的数组元素感兴趣。需要牢记的一点是数组名表示数组的第一个元素的地址,它是一个指针常量,所以不能被原创 2015-02-03 23:42:12 · 660 阅读 · 0 评论 -
《C和指针》笔记
第一个程序是第一章中的例子,第一次使用vim和gcc,花了好长时间才调试好,写完后一直放着没有整理。这里把一些零碎的东西整理一下。这个程序的目的是从标准输入读取文本并对其进行修改,然后把它显示到标准输出。首先读取一行串列标号,这些列标号成对出现,表示输入行的列范围。这串列标号以一个负值结尾。剩余的输入行被程序读入并打印,然后输入行被选中范围的字符串被提取出来并打印。注意,每行第1列的列标号为0原创 2015-02-03 23:17:32 · 562 阅读 · 0 评论 -
c中变量在栈中的地址
观察下面一段代码,看看c中自动变量在栈中的地址关系:#include void func(int a,int b){ printf("a:%p,b:%p\n",&a,&b);}int main(){ int a=0,b=1; printf("real a:%p,b:%p\n",&a,&b); func(a,b);}上面这段代码先打印main函数的栈中的两个自由变量的地址,原创 2015-02-03 22:48:50 · 2247 阅读 · 0 评论 -
C中函数指针的用法
理解了C中的声明和指针的话题后再来看函数指针的用法就很容易了。C中函数指针主要有两个用途:1.作为参数传递给另外一个函数(即作为回调函数)2.转换表(jump table)下面分别来介绍作为回调函数的用法和作为转换表的用法1.回调函数在链表的查找中使查找函数与类型无关/*在一个单链表中查找一个指定值的函数。它的参数是一个指向链表第一个节点的指针 * 一个指向我原创 2015-02-03 21:02:18 · 1125 阅读 · 0 评论 -
双链表操作
处理完了单链表,这次处理双链表。在一个双链表中,每个节点都包含两个指针,指向前一个节点的指针和指向后一个节点的指针。这可以使我们以任何方式遍历双链表,甚至可以忽略前后地在双链表中访问。下面的图示展示了一个双链表:下面是节点类型的声明文件:double_linked_list_node.h#ifndef _DOUBLE_LINKED_LIST#define _DOUBLE_原创 2015-02-03 17:24:13 · 870 阅读 · 0 评论