`
webcenterol
  • 浏览: 917079 次
文章分类
社区版块
存档分类
最新评论

Prefer C++(一)

 
阅读更多

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);可能导致灾难性的后果。

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

 比如API函数原型int SetAbortProc(HDC hdc, ABORTPROC lpAbortProc);

调用时有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

分享到:
评论

相关推荐

    More Effective C++

     More Effective C++一书充满了实用性高且掷地铿锵的忠告,为你每天可能面对的问题带来帮助。和其前一本兄弟书籍 Effective C++一样,More Effective C++对每一位以C++为开发工具的程序员而言,都必备读物。  继 ...

    C++Builder™ 6 Developer’s Guide

    Since different authors have different viewpoints of a product, I always prefer to consult more than one book to gain in-depth knowledge, as every author provides a unique service with his or her ...

    Google C++ Style Guide(Google C++编程规范)高清PDF

    Therefore, we prefer to minimize includes, particularly includes of header files in other header files. You can significantly minimize the number of header files you need to include in your own ...

    More_Effective_C++中文.pdf

     Prefer C++-style casts.  条款3:绝对不要以多态(polymorphically)方式处理数组  Never treat arrays polymorphically.  条款4:非必要不提供 default constructor  Avoid gratuitous default ...

    c++ Effective STL(中文+英文)

    Prefer range member functions to their single-element counterparts...12 Item 6. Be alert for C++'s most vexing parse...................................................20 Item 7. When using containers...

    C++ GUI Qt4编程第二版

    Sure, there are the obvious answers: Qt's single-source compatibility, its feature richness, its C++ performance, the availability of the source code, its documentation, the high-quality technical ...

    Effective C++(第三版)

    条款01:视c++ 为一个语言联邦 view c++ as a federation of languages 条款02:尽量以const, enum, inline替换 #define prefer consts,enums, and inlines to #defines. 条款03:尽可能使用const use const ...

    Using LUA with Visual C++ (Introduction)

    LUA is a scripting language, its power lies in the fact that it can be embedded in your C++ programs. Scripts give you the possibility to change the behaviour of your C++ programs without any need to ...

    程序员面试刷题的书哪个好-effective-cpp-note:EffectiveC++、MoreEffectiveC++和Effective

    一、让自己习惯C++ (Accustoming Yourself to C++ 11) 1. 视C++ 为一个语言联邦 11(View C++ as a federation of languages 11) 主要是因为C++是从四个语言发展出来的: C的代码块({}), 语句,数据类型等, object-...

    linux时间同步ntp服务的安装与配置

    再加上我们的时间同步服务端的IP地址或者域名即可,其中prefer选项表示优先使用该时间同步服务器 #server 0.centos.pool.ntp.org iburst #server 1.centos.pool.ntp.org iburst #server 2.centos.pool.ntp.org ...

    simual-04.rar

    navigational aids and waypoints) and on-screen text and menus (similar to the existing modeless ATC menus), and two new C++ samples have been added to demonstrate the new functions. The functions for...

    Copy Constructors and Assignment Operators终极解释

    I get asked this question sometimes from seasoned programmers who are new to C++. There are plenty of good books written on the subject, but I found no clear and concise set of rules on the Internet ...

    Turbo Assembler 5 (TASM)

    TASM has full 8088, 8086, 80286, 80386, i486, and Pentium support, as well as interface support for C, C++, Pascal, FORTRAN, and COBOL. A full-screen interactive debugger (Turbo Debugger) is also ...

    VclZip pro v3.10.1

    VCLZip Native Delphi Zip/UnZip Component! (VCLZip Lite: Version 2.23 April 14th, 2002) (VCLZip Pro: Version 3.10 Buid 1 - November 25th, 2007) IMPORTANT: If installing the registered version, ...

    vld-2.5.1_2.zip

    Or, if you'd prefer, you can [contribute a small donation][2]. Both are very appreciated. ## Documentation Read the documentation at [http://vld.codeplex.com/documentation]...

    vld-2.5.1-setup.zip

    Or, if you'd prefer, you can [contribute a small donation][2]. Both are very appreciated. ## Documentation Read the documentation at [http://vld.codeplex.com/documentation]...

    opengl画图程序附带源代码

    #include &lt;windows.h&gt; // Header File For Windows #include &lt;gl\gl.h&gt; // Header File For The OpenGL32 Library #include &lt;gl\glu.h&gt; // Header File For The GLu32 Library #include &lt;gl\glaux.h&gt; // Header File...

    ferret-opencv

    雪貂opencv 用于OpenCV...CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")set(THREADS_PREFER_PTHREAD_FLAG ON)find_package(Threads REQUIRED)find_package(OpenCV REQUIRED)add_executable(core core.cpp)target_link_l

    适用于Linux、Mac和Windows的DWService代理

    The code is written in python2 and several libraries are written c++. Start the agent If you prefer you can start the agent from the sources but you keep in mind in this mode the agent does not update...

Global site tag (gtag.js) - Google Analytics