改善C++代码的学习笔记2

来源:互联网 发布:mac 10.12 dns flush 编辑:程序博客网 时间:2024/05/21 17:13

1、使用typedef与#define提高可读性

     对于某些复杂难懂的指针,如void (*p[10]) (void(*)()),谁知道这什么东西?第一个括号中的*p[10]是指针数组,数组中的指针指向以void(*)()为参数的函数,而这个参数void(*)()又是一个指向无参数、无返回的函数指针。对于这些可读性太纠结的东西,我们可以这样来:typedef void (*pfv)()声明无参无返回的函数指针,typedef void (*Keypoint)(pfv)声明指向参数为pfv且无返回的函数指针,Keypoint p[10],终于搞定。    在此处得说明一下,如果有这么两句typedef int* PINT与#define PINT int*的话,请注意,PINT p1,p2可能会让你失望了。如果用的是typedef那会有两个指针,如果是#define会有一个指针与一个整型变量。原因在于typedef一定的封装性

2、优先使用前缀操作符

    这里以自增运算符为例,有能力的同学可以考虑从汇编的角度去比较一下,这里从表面来看看。运行操作符前编译器要去寻找相关的函数,不论前缀还是后缀,都是只有一个参数。为了区别,C++规定后缀形式有一个int型的参数,由编译器传递一个0给该函数。那么我们来比较一下两者的区别吧:
//成员函数重载<类型> ClassName::operator ++();//前缀<类型> ClassName::operator ++(int);//后缀//非成员函数重载<类型> operator ++(ClassName&);//前缀<类型> operator ++(ClassName&,int);//后缀//后缀,构造临时对象保存原值,自增,返回临时对象//前缀,自增,返回
    虽然可能效率上相差不大,但既然有省事的好办法,何乐而不为呢?

3、区分new的三种形态

    new operator/operator new/placement new三种形态。可能我们常见的就是类似于int *ptr=new int类的写法,同时我们也曾写下过classname *ptr=new classname(……)创建一个对象,这就是new operator向内存进行申请。但申请内存又调用operator new,有点重载函数的意思,即void* operator new(size_t size)。而最后一种placement new是C++标准库的一部分,用它来选择合适的构造函数,如果想对未初始化的内存进行处理取得想要的对象,就这样干吧: 
#include #include "classA.h"int main(){       void *s=operator new ( sizeof(A) );       A *p=(A*) s;       new (p) A(2012);//神奇的使用方法       ……       return 0;}             
    真的是哥第一次见到这种东西,new (p) A(2012)在特定的内存上用特定的构造函数创建了一个对象,希望自己手动管理内存就用placement new。总结一下:1、在堆上建立对象,用new operator实现;2、仅仅分配内存,不干其它事,operator new,当然,不满意的话自己重载一个;3、已有内存建立对象,placement new,通常不这么干

4、正确处理new的失败

    面对new的失败,平日里常用if(!ptr){……}等语句。虽然至今没见到过它申请失败的样子,但是对于现在的new而言,它并不会返回一个NULL的指针,反而是抛出一个std::bad_alloc的异常,那么我们就应该采取新式的捕捉异常了:try{int* ptr=new int;……}catch(std::bad_alloce){return false;}。当然了,古老的编译器仍会有返加NULL的情况,但新式的编译器……呵呵,哥没试过。。。

5、掌握定义变量的时机

    C++允许在任意位置定义变量,在遇上定义时,调用相关的构造函数,消去时也会调用其相关的析构函数。在使用变量时,尽量避免其作用域的膨胀,不仅有效减少变量名污染,同时还有利于他人阅读理解。VC6.0中一个与VC2010明显的区别在于for(int i=0;i<N;i++),这里变量i的作用域在两个环境下是不一样的!总之,推迟变量的定义

6、防止重复包含头文件

    平时要#include “classA.h”时,万一这里面包含的与现有的发生重复,那就出错了。常用的办法是#ifdef <project>_<path>_<file>_h  #define ……,当然了,还有一种#pragma once的方法。编译器每次编译时都要打开头文件才可判定是否有重复定义,故大项目里,#ifdef使编译时间较长,而#pragma once的方式由编译器提供,它保证同一个文件不会被包含多次(同一个文件是指物理上一,不是指内容相同的),这种方法在兼容性方面貌似表现不是很好,故常用前者的方法。
原创粉丝点击