1.声明与定义
- 声明:揭示函数/变量的签名,参数和返回类型
- 定义:实际是为各对象分配内存
2.在构造函数前使用explicit关键字
class B
{
public:
B(int x){}
};
有一个函数:
void Fun(B obj);
|调用|说明|有explicit|无explicit|
|-------------|--------------|--------------|
|Fun(2)|隐式转换|错|对|
|Fun(B(2))|显示转换|对|对
|B b; Fun(b);||对|对|
由此可以看出,explicit可以阻止隐式转换,这是好的,因为隐式转换大多数情况不是我们的预期
3.copy构造函数
- 拷贝构造函数的目的是以同类型的对象初始化自我
- 继续使用上面的类B
- **B b1(2) **//调用默认构造函数
- B b2(b1)//调用copy构造函数
- B b3 = b1//调用copy构造函数
- b2 = b1//调用copy操作符
- 后面2个有区别是因为b3是未存在,b2已存在了
4.尽量传引用,不传值
- 因为如果传值的话,实参的值赋值给形参要调用copy构造函数,结束还要析构掉,如果对象有父类和子类,想一想构造函数和析构的代价会更大
5.尽量用const、enum、inline替换#define
- 我们知道#define是预处理的时候直接替换的,编译时的符号表不存在变量的符号,所有如果出错是不好定位到那个变量出错,可能只能看到出错的值。例如别人写的文件里的出错了,是因为它#define的一个变量出错,而你使用了他的文件,出错,完全定位不到哪里出错。
- 所以如果#define定义一个常量,完全可以用const取代
- enum也是类似,可以为常量取一个别名,易读
- inline函数可以提高运行速度,因为它直接嵌入代码中,所以代码段要小
6.预处理器处理
#define、#include、#ifdef/#endif、etc
7.尽量使用const
- 原因:许多编译器对const对象进行了优化,运行速度变快
- const可使用的情况:
- const可修饰类内static或non-static变量
- 可修饰类外global或namespace作用域的对象
- 可修饰文件、函数、块作用域内被声明为static的对象
- const成员变量:
- 明示那个函数可改动对象内容
- 使操作const成为可能(不太懂)
- 成员函数的常量性不同可被重载
总结:
- 某些变量或对象声明为const,编译器可帮助侦错
- non-const版本调用const版本,可避免代码重复
8.确定对象使用前先被初始化
- 准则:确保对象构造函数把每个成员都初始化
- 编译器的不明确行为
- **int x;**对于x,编译器有时会把x初始化为0,有时不会
- 内置类型的初始化
- 自定义类型
- 初始化责任落在类本身,在构造函数进行初始化
- 赋值和初始化的区别
class B
{
public:
B(int x):m_a(x){}
private:
int m_a;
}
上面这个使初始化
class B
{
public:
B(int x){
m_a = x;
}
private:
int m_a;
}
上面这个是赋值
赋值是在构造函数体内完成的,它等于是构造函数已经初始化了,再给类成员赋值,而初始化是在初始化列表中给成员变量初始化,相当于在自身初始化的时候给成员也初始化了,比起赋值,效率坑定高了很多。