Effective C++ 条款04:确定对象被使用前已先被初始化
C++对于自动初始化变量没有一个明确的规定,跟编译器有关。因此,我们应该永远在使用对象之前先将它初始化。
int x = 0;
const char* text = "A C-style string";
// input
double d;
std::cin >> d;
赋值与初始化
我们设计两个类PhoneNumber和ABEntry。PhoneNumber表示电话,ABEntry表示通讯录,用于保存PhoneNumber。
class PhoneNumber{}
class ABEntry{
public:
ABEntry(const std::string& name, const std::string& address, const std::list<PhoneNumber>& phones);
private:
std::string theName;
std::string theAddress;
std::list<PhoneNumber> thePhones;
int numTimesConsulted;
}
当然,这两个类写的过于复杂了。我们只需要关注ABEntry的构造函数就行了。这个构造函数有3个参数,name,address和phones。我们需要用这三个参数构造这类自己的成员变量。
ABEntry::ABEntry(const std::string& name, const std::string& address, const std::list<PhoneNumber>& phones) {
theName = name;
theAddress = address;
thePhones = phones;
numTimesConsulted = 0;
}
如果是这样写的,就是赋值而不是初始化。赋值的步骤是先调用默认构造函数,然后再调用这个构造函数给成员变量赋值。
赋值会导致一个问题,就是在默认构造的时候编译器会给成员变量整一个默认值(或者随机值)。
初始化是下面这样写的
ABEntry::ABEntry(const std::string& name, const std::string& address, const std::list<PhoneNumber>& phones)
:theName(name),
theAddress(address),
thePhones(phones),
numTimesConsulted(0)
{}
初始化直接调用这个构造函数初始化成员变量。这样赋值会调用两次构造函数,而初始化只用调用一次。效率更高一点。
初始化与赋值还有个区别是在初始化成员变量时用的拷贝构造函数,而赋值用的是赋值运算符。
const和引用的成员变量一定需要有初值。所以不能采用赋值的方法,只能通过初始化的形式。
所以类的所有的成员变量都用这种成员列表的方法初始化就行了。虽然有时候成员变量很多的时候看起来会很丑。
初始化次序
类成员的初始化次序是在类定义的时候决定的,比如ABEntry里。theName是第一个,theAddress是第二个,以此类推。
所以我们在用初始化成员列表初始化的时候,最好也按照这个顺序。否则可能会出现一些意想不到的问题。比如我们初始化了一个a,然后想用a去初始化b。但在类的定义中,b比a先定义。
class Test{
public:
Test(int _a)
:a(_a), b(a){}
private:
int b;
int a;
}
我们希望_a先初始化a,然后a再初始化b。但实际上是先a初始化b,然后才是_a初始化a。这就会导致问题。
后面编译的东西以后再说吧...

浙公网安备 33010602011771号