条款四:确定对象在使用前已经初始化
这一条也可以说是在成员定义的时候同时赋予一个初始的数值,有过C编程经验的人对指针定义的初始化应该不陌生,指针
定义的时候同时给予一个初始化的值,一般是为NULL,这样就不会出现野指针的情况,同时在指针空间释放的时候也注意将对应
的指针赋予一个NULL的值,这样就不会出现指针指向一个无效的地址的情况!同样在C++里面,类作为主要的自定义类型,其成员
函数在类对象构造的时候也要做一定的初始化!
附加说一下变量的定义与声明,变量定义是指的编译器会按照变量的类型在内存中申请一定的空间,如果此时你没有对这
块空间做任何的初始化,那么这个变量的值就是这块内存中的数据,这个数据可以是任何无效的数据!相对应的声明主要是告诉编译
器,这个变量或者其他的对象在其他对应已经定义了,这里只是起到一个符号链接的作用,在C++中声明主要包括以下几方面:
1.用extern来声明的变量,包括内置变量或者自定义的变量,例如:extern int number;
2.函数声明,int max(int 1, int b);
3.类的声明;类其实是跟C语言中的struct结构体是相同的,只是默认的成员变量的访问权限不同;
4.模板的声明;template<typename T> class GraphNode;
以上提到的声明在工程中都是要放到对应的.hpp文件中的,其实还有inline函数,模板的定义等也是要放到对应的.hpp
的文件中,总之不涉及到内存空间申请的都是要放到.hpp文件中。
接着将初始化问题,对于内置类型,一般人都没有初始化的习惯,例如对于int类型变量,一般都是定义int tmp;没
有初始化,其实为了统一性和不确定的问题出现,最好也赋予初始值!
对于类的初始化问题,例如:
People类含有三个数据成员,我们要在People对象构造的时候对这些成员进行初始化,对应的我们可以这样写类的构class People{ private: int age_; string sex_; Address addr_; public: .... }
造函数:
People(int age, string sex, Address addr):age_(age),sex_(sex),addr_(addr){}
上面在调用People的构造函数之前就首先对类的成员变量进行了初始化,注意与下面这种方式的区别:
People(int age, string sex, Address addr){ age_ = age; sex_ = sex; add_ = addr; }
虽然这种方式在很多情况下不会出错,但是对程序的性能方面对有影响,第一种方式中,只是调用了对应数据成员的构
造函数,而第二种方式中首先调用了成员的构造函数,然后又调用了成员的赋值构造函数,明显在效率上会有很大的差别!虽然
这两种方式对内置类型的成员函数没有区别,但是为了统一还是建议采用第一种方式!
需要注意的是在第一种方案中,也是就成员的初始化列表中,成员的顺序是有要求的,一般是先父类的成员初始化,然
在本身成员的初始化,在同一对象的成员之间,初始化的顺序最好与成员在类中声明的顺序相同!
在本书中还介绍了一种静态成员变量的初始化问题,这里说的静态变量指的是全局的变量,命名空间变量以及局部的
static成员变量,他们之间存在的依赖关系可能造成不确定的错误;例如在上面的定义的People类中,有一个头文件
people.hpp中包含extern People WHZ;这样当在其余的文件中用到了对象WHZ的时候,如果WHZ还没有进行相关的
初始化,那么将会出现不确定的问题,对应的解决办法是将全局的变量转变为局部的静态变量,例如:
//people.hpp class People{....};, People& getwhz(){ static People whz; return whz; }
//student.hpp class Student{....}; Student::Student(){ ...... int age = getwhz().get_age(); ...... }
这样就保证了在Student对象构建的时候首先能保证People对象是已经初始化的,不会出现引用未初始化成员的情况
这样当你没有调用getwhz的时候也不会对whz这个对象进行构造函数调用,注意局部函数中的static成员是一直存在的,所以
可以返回一个局部static对象的引用。
请记住:
- 为内置型对象进行手工的初始化,因为C++不保证能初始化他们;
- 构造函数最好用成员初始化列表,而不要在构造函数的内部采用赋值操作,初值列表中的成员的顺序要与类中成员的顺序相同
- 为避免"跨编译单元的初始化顺序"问题,建议通过local static对象替换non-local static 对象