<Effective C++>条款02:尽量以const,enum,inline替换#define

         今年8月在HX实习时,组长要求实习生每周要进行代码和编程知识的分享,作为组内为数不多的C++er,想来想去还是总结整理一下Effective C++里的条款,也算自己再进行一遍复习。

  1. 过往我们在C中定义一个常量时,往往使用#define宏定义的方式来进行。为什么呢?

          “const在C中不表示一个变量是常量。const只表示一个变量是只读的。”[1]

          为什么这么说呢?我们可以举一个简单例子:

const int a= 100;

int *pa = &a;

*pa = 200;

printf("%d",a);
    输出结果很有意思,是200,而非100。这是因为在C中,const仅仅是给一个常量赋予了一个只读的属性,这就意味着我们可以通过一个指针“绕过”其只读的性质,从而对它的值进行修改。一个直接的体现就是,在C中不可以使用const int型常量对数组长度进行声明。因此,在许多C代码中,更多的是使用#define来定义常量。

到了C++中,const声明的常量存在于符号表(symbol table)中,不再是“伪常量”。

  1. #define无法创建类的专属常量,当我们使用const来定义类的专属常量时,为了确保此常量只有一个实体,必须使其成为一个static成员:
class Game

{

static const int len = 5;

int nums[len];

}
         ①当类内static常量为int、char、bool类型时,我们可以在类内执行声明+定义(如上所示),但是如果需要取其地址或者编译器要求的话,我们此时还需要在类外(实现文件内)对该常量进行定义:

const int Game::len;//定义,位于实现文件内

        ②当类内static常量非上述类型时,就必须执行类内声明+类外定义了:

class Game

{

static const double num ;//声明,位于头文件内

}

double Game::num = 8.2;//定义,位于实现文件内 


当然,int/char/bool也支持这种方式。

  1. 2.中提到,static const int型的常量类内声明定义或者类内声明+类外定义都可以,但是如果我们还需要该常量来说明类内一个数组的长度时,就必须执行类内声明+定义了:
class Game

{

static const int len = 5;

int nums[len];

}


However,有些老式编译器却又不支持上述的类内初始化,那该怎么办呢?我们可以使用enum来充当类内常量:

class Game

{

enum{ len = 5};

int nums[len];

}


  1. 使用#define来定义宏是一种常见的套路:
#define  CALL_MAX(a,b) fuction((a) > (b) ? (a) : (b))

inta = 5, b = 0;


CALL_MAX(++a, b);//a被累加2次

CALL_MAX(++a, b + 10);//a被累加1次

a的递增次数竟取决于“它被拿来和谁比较”,这样的特性十分隐蔽且无用。

那么,

如何获得类似宏定义的效率?利用inline函数:

如何获得类似宏定义的泛型特性?利用泛型编程:

template<typenameT>

Inline void call_max(const T& a, const T&b)//获得一整群函数,以支持泛型

{

f(a> b ? a : b);

}


总结:

①对于单纯常量,最好以const对象或者enum来代替#define;

②对于形似函数的宏,最好改用inline函数来代替#define;

reference:

[1]https://www.cnblogs.com/collectionne/p/6713651.html




猜你喜欢

转载自blog.csdn.net/gsafjhbfqwergerkbvgk/article/details/78861774