C 程式设计最好实践(1)

2008-02-23 05:29:32来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

随着电脑语言的发展,我们现在编写一个程式越来越容易了。利用一些软件研发工具,往往只要通过鼠标的拖拖点点,电脑就会自动帮您生成许多代码。但在很多时候,电脑的这种能力被滥用了,我们往往只考虑把这个程式搭起来,而不去考虑程式的性能如何,程式是否足够的健壮。而此节课的目的主要是介绍一些编码的经验,让大家编写的程式更加健壮和高性能。

  1、Prefer const and inline to #define

  在C 编程中应该尽量使用const和inline来代替#define,尽量做到能不用#define就不用。#define常见的用途有“定义常量”连同“定义宏”,但其中存在诸多的弊病。

  第一,查错不直观,不利于调试。Define的定义是由预处理程式处理的,作的是完全的文本替换,不做任何的类型检查。在编译器处理阶段,define定义的东西已被完全替换了,这样在debug的时候就看不到任何的相关信息,即跟踪时不能step into宏。例如,把ASPECT_RATIO用define定义成1.653,编译器就看不到ASPECT_RATIO这个名字了。假如编译器报1.653错,那么就无从知道此1.653来自于何处。在真正编码的时候应该使用如下的语句来定义:


static const double ASPECT_RATIO = 1.653;

  第二,没有任何类型信息,不是type safe。因为他是文本级别的替换,这样不利于程式的维护。

  第三,define的使用很容易造成污染。比如,假如有两个头文档都定义了ASPECT_RATIO, 而一个CPP文档又同时包含了这两个头文档,那么就会造成冲突。更难查的是另外一种错误,比如有如下的代码:
  // in header file def.h
  #define Apple 1
  #define Orange 2
    #define Pineapple 3
   …
  // in some cpp file that includes the def.h
  enum Colors {White, Black, Purple, Orange};

  在.h文档中Orange被定义成水果的一种,而在.cpp文档中Orange又成为了一种颜色,那么编译器就会把此处的Orange替换成2,编译可能仍然能够通过,程式也能够运行,但是这就成了一个bug,表现出古怪的错误,且很难查错。再比如定义了一个求a和b哪个数大的宏,#define max(a,b) ((a) > (b) ? (a) : (b))
  int a = 5, b = 0;
  max( a, b);
  max( a, b 10);

  在上面的操作中,max( a, b); 语句中a被 了两次,而max( a, b 10); 语句中a只加了一次,这样在程式处理中就很有可能成为一个bug,且此bug也很的难找。在实际编码时能够使用如下的语句来做:
  template
  inline const T&
  max(const T& a, const T& b) { return a > b ? a : b; }

  2、Prefer C -style casts

  在程式中经常会需要把一种类型转换成另外一种类型,在C 中应该使用static_cast、const_cast、dynamic_cast、reinterpret_cast关键字来做类型转换。因为这有以下好处,一是其本身就是一种注释,在代码中看到上面这些关键字就可马上知道此处是进行类型转换。二是C语言中类型转换通常是很难进行搜索的,而通过关键字cast则能够很容易的找到程式中出现类型转换的地方了。

  3、Distinguish between prefix and postfix forms of increment and decrement operators

  通常对于操作系统或编译器自身支持的类型,prefix(前缀,如 i)和postfix(后缀,如i )的效果是相同的。因为现在的编译器都很聪明,他会自动做优化,这两者的汇编代码是相同的,性能不会有差别。但有时候也会有不同的,如一些重载了操作符的类型。下面是模拟prefix和postfix的操作过程,能够发现在postfix操作中会生成一个临时变量,而这一临时变量是会占用额外的时间和开销的。
  // prefix form: increment and fetch
  UPInt& UPInt::operator ()
   {
    *this = 1; // increment
   return *this; // fetch
   }
  // postfix form: fetch and increment
   const UPInt UPInt::operator (int)
   {
    UPInt oldValue = *this; // fetch
    (*this); // increment
    return oldValue; // return what was fetched
   }

  一般情况下无需区分是先 ,还是后 ,但是我们在编写程式的时候最好能习惯性的将其写成 i的形式,如在使用STL中的iterator时,prefix和postfix会有相当大的性能差异。请不要小看这些细节,实际在编写程式的时候,若不注意具体细节,您会发现程式的性能会很的低。但要注意,虽然在大多数情况下能够用prefix来代替postfix,但有一种情况例外,那就是有[]操作符时,比如gzArray [ index] 是不等于 gzArray[index ]的。


[1] [2] 下一页

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: C 中的虚函数(virtual function)(1)

下一篇: VC .net 整合研发环境使用技巧(1)

热门词条
热门标签