Prefer C++(一)

原创 2003年12月07日 22:29:00

Prefer C++<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

Written by 李智勇

前言

读了《Eric Raymond对于几大开发语言的评价》一文,觉得其对C++的评价极其偏颇。C++本身支持多典范设计,也就是说你可以完全不用OO,GP而只采用结构化的方法去进行程序设计。这个时候同C相比,效率是基本一致的。而确可以享受到更严格的类型系统检查、inline函数、名字空间、运算符重栽所带来的益处。如果你牺牲一点效率,你还可以使用异常处理。

我以前为项目组成员写过一篇文章,号召大家从C转向C++。现贴出此文,望方家斧正。

 

1、比C更严格的类型系统

        char szBuf[MAX_PATH];

        WORD j=szBuf;

        C里面是允许的是个警告,而在C++里面则非法是错误。

        WORD Add(WORD a,WORD b);

           Add(1,szBuf);可能导致灾难性的后果。

更关键的是处理回调函数时:

比如

                     调用时有SetAbortProc(hdcPrn, AbortProc)

如果AbortProcABORTPROC类型不符,在c里边将自动转换类型。绝对可能导致灾难性的后果。此时堆栈会如何?

总之C++在防范失误所引起的错误方面做的更好,但绝对不禁止故意打破类型系统的行为。由于必须兼容C,C++做的也不好,警告后还是要做类型转换的。看下面这个例子:

    int a=0;

    unsigned b=0;

    int i;

    for(i=10; i>=b; --i)

        {

         a++;

        }

 

 

 

其实这是个死循环。问题出在i和b类型不匹配(编译时这是个警告,而不是错误)。当必须进行比较时,都会被转成unsigned,于是i>=b将永远为true。

 

2、智能化的资源管理

利用C++的构造和析构函数可以建立非常完善的资源管理机制,尽可能的防止资源泄露。看下面的程序段:

void func1()

{

     char* szBuf=malloc(50);//利用C中void* 到其他类型指针的自动转换

 

     --------

 

     free(szBuf);

     return ;

}

   这样在分配和释放内存之间的任何一个地方,如果需要返回,则必须有这种形式的代码:

if(---)

{ free(szBuf); return 0;}

而一旦忘记释放内存而返回,必将产生内存泄露。

 

C++类的实例有这样一种特性。在其作用域开始的时候,构造函数被调用,超出作用域时析构函数被调用。利用这一规律来管理资源的最有名的例子是标准库中的智能指针(参看:More Effevtive C++,The C++ Standard Library及The C++ Programming Language。

下面简要说明其原理:

Class A;

void func2()

{

    A  a; //构造函数被调用

    ------

    return; //析构函数被调用

}

如果在Class A的构造函数中完成相关资源分配,在析构函数中释放内存会怎样?

分配内存后再不用担心释放的问题了。

 

A大致有如下的形式:

typedef struct tagPoint

{

    int x;

    int y;

}Point,PPoint;

 

Class A

{

    PPpoint pointer;

    SmartPointer(PPpoint p)

    {  

        pointer=p;

    }

 

    ~SmartPointer()

    {

        if(pointer)

        delete pointer;

    }

 

    Point & operator*() const

    {

        return *pointer;

    }

    Point * operator->() const

    {

        return pointer;

    }

};

这样用到Point时就可以这样:

A pointer(new Point);//为Point结构分配了内存

pointer->x=5;        //存取相关元素

//超出作用域时为Point分配的内存将被自动删除

 

而为每一个结构都写一个类不划算,所以人们发明了模板。应用模板时A被定义成这个样子:

 

template <typename T> class SmartPointer

{

    SmartPointer(T* p)

    {  

        pointer=p;

    }

 

    ~SmartPointer()

    {

        if(pointer)

        delete pointer;

    }

 

    T& operator*() const

    {

        return *pointer;

    }

    T* operator->() const

    {

        return pointer;

    }

 

private:

    T* pointer;

};

这样不管什么结构,都可以用A了。

使用时是这样:

A<Point> pointer(new Point);

pointer->x=5;

//超出作用域时为Point分配的内存将被自动删除

 

 

N多人阐述过这个观点,但我觉得在windows下最有用的是附件1。

可实现对Windows下各种句柄的智能化管理。

作者:Jeffey Richter 2000年第四期msdn杂志,win32 Q&A专栏

 

读懂这个例子需要一点模板和符号重载的知识。

用起来很简单:

比如对于文件句柄,有:

CensureCloseHandle hHandle=CreateFile(---);

WriteFilehHandle;

----------

不用调用CloseHandle了,超出作用域它将被自动调用。

 

最嚣张的应用是有引用记数的智能指针。

见附件2。(Come from the C++ standard library)

3、强大的inline(C不支持这个吧!)

第一次看Link-time Code GenerationMatt Pietrek MSDN magazine 2002 5别的也没记住,就记了个通过链接器自主选择那些函数可以做inline可大幅度提高性能。后来自己就在vc++上试了一下,结果还是真恐怖,先说性能最多能提高多少,看下面的程序,并猜猜inline函数所花费的时间:

int add(int a,int b)

{

       return a+b;

}

 

inline int addinline(int a,int b)

{

       return a+b;

}

 

都是以这种形式进行调用:

    int b;

    for(int j=0;j<50000;j++)

    {

        b=add(60,70);

    }

假设add()所花费的时间是:88964ns(vc++ 6.0 release 版本下),那么addinline所花费的时间是多少?

 

 

真实结果是0,也就是说addinline函数根本不存在。被优化后,剩下的只是一个值0x82。当然这是一个极端的例子,但从另一个角度讲把适当的函数做成inline实际上是给编译器,连接器做出更大优化的机会。

 

inline的另一个优势。

大家都知道,函数调用要处理堆栈(很少是寄存器)。这样就有一部分进栈和出栈的指令,这部分代码对于inline是没有的。

for(int j=0;j<50000;j++)

       {

              b=add(j,j+1);

       }

for(int p=0;p<50000;p++)

       {

              b=addinline(p,p+1);

       }

cout<<b;//必须使用一下b

此时所耗费的时间两者分别为:

1.10619e+006ns 和331754ns

 

 

NTP原理初步与配置

1)        Ntp基本原理 Server和·Client之间的同步(C/S模式) 1.主机启动ntp daemon 2.Client向NTP Server 发送调较时间的申请 3.NT...
  • GrubLinux
  • GrubLinux
  • 2014年05月16日 19:56
  • 3385

Android网络请求:OkHttp实战

android网络请求是个耗时的操作,一定要在子线程中运行,添加网络权限,目前有很多流行的网络框架。比如okhttp,volley,xutils等等。今天主要介绍okhttp的使用,后续分享给多,比如...
  • dzsw0117
  • dzsw0117
  • 2016年04月23日 21:45
  • 2055

制作pypi上的安装库

下载地址 如何制作分发工具呢 setuppy 源码包 其他文件 制作过程 首先上场的肯定是setuppy了如下 然后是LICENCE 注册 测试 总结自从接触Python依赖也有几个月了,虽然主要的开...
  • Marksinoberg
  • Marksinoberg
  • 2016年10月08日 18:58
  • 6607

centos NTP服务器配置总结

centos NTP服务器配置总结 2013-07-10 18:06:55 标签:同步 ntp 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否...
  • hqyhqyhq
  • hqyhqyhq
  • 2013年12月09日 16:26
  • 1297

android 6.0 优先网络类型设置流程(Preferrred network type)

本文主要介绍在settings –> Mobile network –> Preferred network type 选择某个网络类型的流程整体流程图重点代码分析1、是否包含global选项最开始执...
  • michael_yt
  • michael_yt
  • 2016年07月07日 11:24
  • 4973

SVN的Merge命令解析

合并包含两点,首先2个版本库树比较,然后将区别应用到本地拷贝。          这个命令包括3个参数: 初始的版本树(通常叫做比较的左边,FROM)最终的版本树(通常叫做比较的右...
  • wjtxt
  • wjtxt
  • 2013年02月28日 10:34
  • 10394

Rather than与prefer to的用法有什么区别

最佳答案 在英语中,表示“偏爱”、“优先”、“更喜欢”、“更可取”或“宁愿”等意思时,可用prefer,would rather和rather than来表达。三个词之间在表达和用法上的异同如下: ...
  • bumingxuexing
  • bumingxuexing
  • 2013年04月18日 11:23
  • 292

【Android 数据业务解析】PreferredApn修改的源码分析

DcTracker中需要去获取preferredapn的id以及修改preferredapn的id,涉及到两个方法的使用,如下: getPreferredApn方法 // 得到prefer...
  • For_Forever
  • For_Forever
  • 2017年07月16日 12:23
  • 428

codeblocks使用cppcheck检查代码

cppcheck是一个静态代码检查工具,能够根据代码分析一些可行的优化方向,但是并不是完全准确,不是完全准确,不是完全准确,重要的事情所以需要说三次。 cppcheck是一个可以单独使用的工具,存在...
  • u010953266
  • u010953266
  • 2015年09月23日 17:23
  • 1210

ntp服务器搭建及客户端配置-使用阿里云

1. NTP服务器搭建 安装ntp yum install -y ntp 2. 外网使用阿里云ntp服务器作为基准阿里云ntp服务器列表:time1.aliyun.comtime2.aliyun.co...
  • sxhong
  • sxhong
  • 2017年11月27日 14:41
  • 237
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Prefer C++(一)
举报原因:
原因补充:

(最多只允许输入30个字)