libsvm代码阅读(2):svm.cpp浅谈和函数指针(转)

svm.cpp浅谈

svm.cpp总共有3159行代码,实现了svm算法的核心功能,里面总共有Cache、Kernel、ONE_CLASS_Q、QMatrix、Solver、Solver_NU、SVC_Q、SVR_Q 8个类(如下图1所示),而它们之间的继承和组合关系如图2、图3所示。在这些类中Cache、Kernel、Solver是核心类,对整个算法起支撑作用。在以后的博文中我们将对这3个核心类做重点注解分析,另外还将对svm.cpp中的svm_train函数做一个注解分析。

图1

 图2

图3

 
下面先看看svm.cpp的前几行代码,主要是几个inline函数,inline函数解决频繁调用小函数大量消耗栈空间的问题。
[cpp]    view plain  copy  在CODE上查看代码片  派生到我的代码片
<EMBED id=ZeroClipboardMovie_1 height=18 name=ZeroClipboardMovie_1 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=1&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">
  1. #include "svm.h"  
  2. int libsvm_version = LIBSVM_VERSION;  
  3.   
  4. typedef float Qfloat;  
  5. typedef signed char schar;  
  6.   
  7. //inline函数解决频繁调用小函数大量消耗栈空间;static函数为静态函数/或内部函数,指函数的调用范围只局限于本文件  
  8. #ifndef min  
  9. template <class T> static inline T min(T x,T y) { return (x<y)?x:y; }  
  10. #endif  
  11. #ifndef max  
  12. template <class T> static inline T max(T x,T y) { return (x>y)?x:y; }  
  13. #endif  
  14. template <class T> static inline void swap(T& x, T& y) { T t=x; x=y; y=t; }  
 
下面这个是clone函数( 一个完全克隆函数,操作结束后,内部的所有数据和指针完全一样),刚开始看的时候对clone的形参T*& dst不太了解,后来才知道这是指针的引用,就是说在函数里面指针的改变等同于形参的改变。关于  memcpy和*&的具体解释我参看我的博文   常见的C++知识 。
[cpp]    view plain  copy  在CODE上查看代码片  派生到我的代码片
<EMBED id=ZeroClipboardMovie_2 height=18 name=ZeroClipboardMovie_2 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=2&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">
  1. template <class S, class T> static inline void clone(T*& dst, S* src, int n)  
  2. {  
  3.     dst = new T[n];  
  4.     memcpy((void *)dst,(void *)src,sizeof(T)*n);  
  5. }  
 
下面这个是幂次函数,写得挺好的, 对幂次为偶数有优化。当为powi(3,5)时,是这样的3*(81),即把3^5=3*(3^4)
[cpp]    view plain  copy  在CODE上查看代码片  派生到我的代码片
<EMBED id=ZeroClipboardMovie_3 height=18 name=ZeroClipboardMovie_3 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=3&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">
  1. static inline double powi(double base, int times)  
  2. {  
  3.     double tmp = base, ret = 1.0;  
  4.   
  5.     for(int t=times; t>0; t/=2)  
  6.     {  
  7.         if(t%2==1) ret*=tmp;  
  8.         tmp = tmp * tmp;  
  9.     }  
  10.     return ret;  
  11. }  
 
以下几个是调试信息输出 
[cpp]    view plain  copy  在CODE上查看代码片  派生到我的代码片
<EMBED id=ZeroClipboardMovie_4 height=18 name=ZeroClipboardMovie_4 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=4&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">
  1. static void print_string_stdout(const char *s)  
  2. {  
  3.     fputs(s,stdout);  
  4.     fflush(stdout);  
  5. }  
  6. static void (*svm_print_string) (const char *) = &print_string_stdout;  
  7.   
  8. #if 1  
  9. static void info(const char *fmt,...)  
  10. {  
  11.     char buf[BUFSIZ];  
  12.     va_list ap;  
  13.     va_start(ap,fmt);  
  14.     vsprintf(buf,fmt,ap);  
  15.     va_end(ap);  
  16.     (*svm_print_string)(buf);  
  17. }  
  18. #else  
  19. static void info(const char *fmt,...) {}  
  20. #endif  

函数指针专题

在libsvm中有如下代码:

 

[cpp]    view plain  copy  在CODE上查看代码片  派生到我的代码片
<EMBED id=ZeroClipboardMovie_5 height=18 name=ZeroClipboardMovie_5 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=5&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">
  1. static void print_string_stdout(const char *s)  
  2. {  
  3.     fputs(s,stdout);  
  4.     fflush(stdout);  
  5. }  
  6. static void (*svm_print_string) (const char *) = &print_string_stdout;  

我在论坛中曾经发帖:

 

看了Pump天天学习同学的回复,我才回想起来:第六行那原来是个函数指针,平时没用到,就给忘了,只能拿出教材重新来学习一遍:

函数指针是指向函数而非指向对象的指针。像其他指针一样,函数指针也指向某个特定的类型。函数类型由其返回类型以及形参表确定,而与函数名无关:

 

[cpp]    view plain  copy  在CODE上查看代码片  派生到我的代码片
<EMBED id=ZeroClipboardMovie_6 height=18 name=ZeroClipboardMovie_6 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=6&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">
  1. // pf points to function returning bool thar takes two const string references  
  2. bool (*pf) (const string &, const string &);  

这个语句将pf声明为指向函数的指针,它所指向的函数带有两个const string &类型的形参和bool类型的返回值。

 

注意:*pf两侧的圆括号是必需的,若没有,则就不是函数指针了。

 

[cpp]    view plain  copy  在CODE上查看代码片  派生到我的代码片
<EMBED id=ZeroClipboardMovie_7 height=18 name=ZeroClipboardMovie_7 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=7&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">
  1. // declares a function named pf that returns a bool*  
  2. bool *pf (const string &, const string &)  


typedef简化函数指针的定义

 

函数指针类型相当冗长。使用typedef为指针类型定义同义词,可将函数指针的使用大大简化

 

[cpp]    view plain  copy  在CODE上查看代码片  派生到我的代码片
<EMBED id=ZeroClipboardMovie_8 height=18 name=ZeroClipboardMovie_8 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=8&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">
  1. typedef bool (*cmpFn)(const string &, const string &)  

该定义表示cmpFn是一种指向函数的指针类型的名字。该指针类型为:“指向返回bool类型并带有两个const string 引用形参的函数的指针”。在要使用这种函数指针类型时,只需直接使用cmpFn即可,不必每次都把整个函数类型声明全部写出来。

 


通过指针调用函数

指向函数的指针可用于调用它所指向的函数,可以不需要使用解引用操作符,直接通过指针调用函数:

 

[cpp]    view plain  copy  在CODE上查看代码片  派生到我的代码片
<EMBED id=ZeroClipboardMovie_9 height=18 name=ZeroClipboardMovie_9 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=9&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">
    1. bool lengthCmp(const string&, const string &);  
    2. cmpFn pf = lengthCmp;  
    3. lengthCmp=("hi","bye");//direct call  
    4. pf("hi","bye");//equivalent call: pf1 implicitly dereferenced  
    5. (*pf)("hi","bye");//equivalent call: pf1 explicitly dereferenced  

转载于:https://www.cnblogs.com/Miliery/p/4394118.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值