今年8月在HX实习时,组长要求实习生每周要进行代码和编程知识的分享,作为组内为数不多的C++er,想来想去还是总结整理一下Effective C++里的条款,也算自己再进行一遍复习。
- 过往我们在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)中,不再是“伪常量”。
- #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也支持这种方式。
- 2.中提到,static const int型的常量类内声明定义或者类内声明+类外定义都可以,但是如果我们还需要该常量来说明类内一个数组的长度时,就必须执行类内声明+定义了:
class Game
{
static const int len = 5;
int nums[len];
}
However,有些老式编译器却又不支持上述的类内初始化,那该怎么办呢?我们可以使用enum来充当类内常量:
class Game
{
enum{ len = 5};
int nums[len];
}
- 使用#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