1,尽量用const或者enum代替#define。
#define,在预编译的时候,系统只是进行单纯的文本替换,而不存在类型检查,所以可能存在风险。
2,对于形似函数的宏定义,最好用inline模板进行替换。
#define只是进行文本替换,虽然不会带来函数的额外开销,但有时候很出错,尽管给宏的“实参”加上括号,也不能彻底避免,例如:
#define CALL_WITH_MAX(a,b) func((a)>(b)?(a):(b))
int a = 10, b = 5;
CALL_WITH_MAX(++a, b); //此处a累加了两次
CALL_WITH_MAX(++a, b+10); //此处a累加了一次
这里依旧会导致导致奇怪的bug。
3,尽量多使用const。
当const修饰指针的时候,如果const在*左边,表示指针指向的变量是常量,如果const在右边,表示这个指针是常量;如果都存在,则表示都是常量。所以我们在定义不可改变的字符串的时候,最好像这样:
const char* const name1 = "beijing";
const std::string name2 = "beijing";
对于stl中的迭代器,也可以用const修饰,而且也存在const_iterator。
std::vector<int> intVector{1,3,5,7};
const std::vector<int>::iterator iter = intVector.begin();
*iter = 10;
iter++; //错误,因为iter为const;
std::vector<int>::const_iterator citer = intVector.begin();
*citer = 5; //错误,因为*citer为const
citer++;
用const修饰函数的返回值,可以在保持安全性和高效性的基础上减少程序员失误造成的意外。而对于函数的参数,如果我们没有修改参数的必要时,也可以修饰为const,预防一些错误,如不小心把"=="写成了"="而引发的未知错误。
此外,也可以把const当作函数重载的标准。
https://mp.csdn.net/mp_blog/creation/editor
public:
void func()const
{
std::cout << "const" << std::endl;
}
void func()
{
std::cout << "non-const" << std::endl;
}
或者:
void func(int const*b)
{
std::cout << "const" << std::endl;
}
void func(int *b)
{
std::cout << "non-const" << std::endl;
}
此外,我们可以用mutable来解除const的限制。
public:
void func()const
{
c = 10;
std::cout << "const" << std::endl;
}
private:
mutable int c = 0;
但是,当const和non-const成员函数内容相同的时候,我们应该只保存non-const版本避免代码重复。
4,在变量使用前将其初始化。
不要混淆了变量的初始化与赋值。
成员变量的初始化发生在构造函数之前,也就是说在构造函数中是对成员变量的赋值,而非初始化。
成员变量的初始化有两种,一种是声明的时候进行定义,另一种是成员列表初始化,两种都可以进行初始化。但是如果两种都使用了,编译器只会默认调用列表初始化。
class B {
public:
B() :a(A(5))
{
a = A(3); //此处为赋值
}
public:
A a = A(8);
};
这种情况下,只会调用A(5)和A(3)。使用列表初始化的效率比较高。如果我们只在构造函数里进行赋值的方式“初始化”,那么编译器会调用成员变量的默认构造函数,然后在再构造函数中对成员变量进行赋值,这样就带来了不必要的开销。甚至如果没有合适的构造函数,会报错。
此外,对于const成员变量,无法进行赋值,所以只能在声明的时候初始化,或者用成员列表初始化的方式初始化。
此外,基类的初始化早于派生类,而且非成员变量是按照声明的顺序进行初始化。静态成员变量的初始化是最先完成的。
对于每一个编译文件(cpp)和他们包含的头文件组成一个编译单元,对于不同单元的non_local static(函数内声明的static对象为local static,其他的被称为non-local static)对象的初始化没有固定的顺序。(不是很理解)。
为了避免不同编译单元的初始化次序问题,最好用local static代替non-local static,可以考虑用单例的方式来实现这个需求。