摘要: 反转链表非常简单,循环链表把next拆开指向前一个就行了在循环的过程中用了临时变量last来表示上一次反转到哪里了,同时用临时变量second表示下一次需要反转的因为当前的next已经被拆断指向前面一个。 阅读全文
posted @ 2011-01-26 19:22 霞光照耀 阅读(370) 评论(0) 推荐(0) 编辑
摘要: NLP的文本分类过程中,大多会统计文章的词频,这是分类的重要依据之一。词频是由一个pair组成的,word是keyfrequece是value。用什么方法统计最好,当然是map。用vector,list也可以实现,但是它们基于关键字的检索效率没有map高,map一般是用rb-Tree实现的,查找效率是O(log(n)),list,vector都是线性的,查找复杂度是O(n)。  先上代码。headercpp[代码]  实现的方式很简单,首先把从文件里load出text,然后去掉里面的符号,最后扫描一遍文件,遇着单词就塞到map里面.这句话太好用了。一句话实现插入map,如果有就增加value, 阅读全文
posted @ 2010-12-25 21:15 霞光照耀 阅读(968) 评论(0) 推荐(0) 编辑
摘要: 昨天看C++里面的容器部分,发现vector的特性很独特:vector对于随机访问有很好的效率,猜想可能是顺序存储vector对随机插入和删除的效率不高,这种特性也是由顺序存储引起的vector容器的容量是自增长的,并不是一开始申请很大一块内存然后直到撑满,而是满了后容量加倍。这种特性跟delphi的TList特别像,在delphi里面,放一个array of pointer的指针,这个指针所指向的空间的内存是动态增长的,容量到达后就增加一个delta,它的增删改查,分别是这么实现的:增加分为两种情况:  (1)在末尾增加:首先判断容量满了没有,如果没有满则直接在数组后面赋值,如果满了就要增加 阅读全文
posted @ 2010-12-23 21:23 霞光照耀 阅读(401) 评论(0) 推荐(0) 编辑
摘要: 上面的例子偷出了类里面protected修饰的函数;这个例子对理解对象内存结构有很大帮助。类里面如果什么都没有,sizeof的结果是1,测试过里面放的是0;类里面如果仅仅有一个虚函数,那么对象内存里面存的就是虚函数表的指针将对象指针解引用就是虚函数表的指针,再解引用就是虚函数表的首函数地址。需要注意虚函数是倒着存的,要得到第二个就要地址减4;上述代码运行后能执行类里面的那两个虚函数。 阅读全文
posted @ 2010-12-21 15:03 霞光照耀 阅读(305) 评论(0) 推荐(1) 编辑
摘要: 当一个类的成员里面有指针的时候,使用默认拷贝构造函数的时候就会造成多个对象管理同一块内存这样带来的后果就是,如果任意一个对象释放了这一块内存,那么其他的对象再来操作这块内存的时候就会发生预料不到的结果。为了避免对象中保存野指针从而引发的错误,提出了智能指针, 它能实现多个对象共享内存的自释放。  其实这种实现有点类似于delphi中的接口,到处传来传去的,最后自释放,就是因为接口有引用计数,当引用计数为1的时候就把对象释放掉。  C++中这种实现(C++ Primer书上借鉴来的),有几个比较巧妙的地方Has_Ptr这个类其实是想保存一个int *的指针,为了避免悬垂指针的出现,我们使用了 I 阅读全文
posted @ 2010-12-19 21:36 霞光照耀 阅读(1426) 评论(0) 推荐(0) 编辑
摘要: C++里面的static修饰的成员,不管是数据还是函数,他都输独立于对象而存在的,对象没有创建的时候它就存在换一句话会所,static修饰的成员是不属于任何一个对象的,它是属于类的。注意Object和class 的区别。类里面的非static的成员函数在对象没有创建的时候是不能使用的,static的成员可以通过TestClass::来访问。因此非static的成员函数能访问static的变量以及函数static的成员函数不能访问非static的变量和函数,因为对象还没有创建static的成员函数类似于delphi中的class function, 在class function中self指针指 阅读全文
posted @ 2010-12-19 10:48 霞光照耀 阅读(639) 评论(0) 推荐(0) 编辑
摘要: 众所周知C++包罗万象,支持很多范式。C++语言似乎就是想包容一切其他语言的优点,讲选择某写范式的权利留给语言使用者,这对于程序员来说,意味着自由。但是太大的自由往往意味着犯错,东西太广阔了,总有记不住的某些细节,譬如下面的代码[代码]这样的代码也能编译通过且赋值成功,真的很灵活。但是灵活的同时会造成程序的可读性变得很差,不加注意可能会产生某些莫名奇妙的bug;其实我更加喜欢严格的有些偏执的代码,严格有些偏执的编译器,让程序员减少出错的机会。幸好C++也考虑到了严格的禁止这种隐式类型转换,只要打开上述代码中的 //explicit 注释, 下面的直接赋值就会被编译器查出编译不过 阅读全文
posted @ 2010-12-18 22:28 霞光照耀 阅读(312) 评论(0) 推荐(0) 编辑
摘要: 我们可以思考一下,当我们定义一个形式上空的类,C++为这个类提供了哪些默认功能?是否可以说齐全呢?有些看起来理所当然的东西,也是需要默认实现的。看简单代码另外注意语句仅仅调用了拷贝构造函数。区分"="是赋值还是copy constructor的关键就是要看"="左边的对象已经构造了没有如果已经构造了,就是进行赋值操作如果还没有构造,就是进行copy构造函数下面的代码证明了上述观点代码运行结果为Default ConstructorCopy ConstructorCopy ConstructorDefault ConstructorAsign Value Operator0 4247360 -1 阅读全文
posted @ 2010-12-18 21:59 霞光照耀 阅读(1548) 评论(1) 推荐(0) 编辑
摘要: 今天试验了一下C++利用windows api调用dll。dll代码是用delphi编译出来的,调用的代码是C++。先看delphi写的dll代码再看C++调用代码其实编译好的二进制文件例如exe和dll在运用的时候都会映射到内存中去。因此只要在这段映射的内存中找到需要调用的函数的地址,并且知道函数的调用形式就可以用函数指针加以调用。在delphi代码中,我们可以看到Add函数带有两个参数,并且标明了是stdcall的调用形式,export标明了导出函数是Add在C++代码中,我们用到了两个api函数第一个是LoadLibrary函数,它的作用是将dll映射到内存,并且返回句柄第二个函数是Ge 阅读全文
posted @ 2010-12-17 22:32 霞光照耀 阅读(521) 评论(0) 推荐(0) 编辑
摘要: p是一个指向int的指针, 强制初始化为内存地址为100的指针, p+100是p向下偏移100个int存储空间(4)后的地址, 强制转化成整形后应该输出100+100*4=500.注意: 不能随意操纵p指向的内容.a退化为a[0]的指针, 那么a+1就是指向a[1]的指针, 所以*(a+1)的结果是2;&array是取int[5]的地址, 因此&array是指向int[5]的指针,... 阅读全文
posted @ 2010-04-27 16:27 霞光照耀 阅读(263) 评论(0) 推荐(0) 编辑