文章目录
- 对象、内置类型在使用前一定要初始化
- 尽量使用初始化列表
- 初始化的顺序
- 不同转换单元的非局部静态对象初始化
- 参考资料
对象、内置类型在使用前一定要初始化
- 内置类型需要手动初始化
int x=0;
const char* text="A C-style string";
double d;
std::cin>>d;
- 对象通过构造函数初始化
class Entry{
public:
Entry(const std::string& name,const std::string& adress);//构造函数进行初始化
private:
std::string theName;
std::string theAdress;
int TimesConsulted;
};
Entry::Entry(const std::string& name,const std::string& adress){
theName=name;
theAdress=adress;
TimesConsulted=0;
}
尽量使用初始化列表
- 在上述代码中,构造函数体内进行了对象的初始化。但是事实上,这并不是初始化,而是进行的赋值操作。
- 因为在进入构造函数的函数体前,除了内置类型如int类型的TimesConsulted,string类型如theName已经调用缺省的构造函数初始化了。
- 为了更高的效率,我们尽量使用初始化列表进行初始化。
- 这是因为成员初始化列表中的参数被string类型缺省的构造函数当做参数进行了初始化。
- 如此只调用了一次拷贝构造函数,否则会调用一次缺省构造函数和拷贝复制运算符。
Entry::Entry(const std::string& name,const std::string& adress):theName(name),theAdress(adress),TimesConsulted(0){}
- 注意事项:const或者引用必须使用初始化列表,他们不能被赋值,只能被初始化。
初始化的顺序
- 基类在派生类之前被初始化。
- 同一个类中,数据成员初始化顺序按照声明的先后顺序进行初始化。
- 初始化列表中的顺序尽量和类中数据成员声明的顺序保持一致。
不同转换单元的非局部静态对象初始化
- 转换单元,可以行程一个单独的目标文件的源代码。
- 静态对象,生存期从它被创建开始,一直到main函数执行完毕。会自动调用他们的析构函数。
class FileSystem{
public:
std::size_t numDisks() const;
};
extern FileSystem tfs;//the file system,未初始化的对象
class Directory{
public:
Directory();
};
Directory::Directory(){
std::size_t disks=tfs.numDisks();//构造函数,可能使用了未初始化的tfs
}
Directory tempDir();//生成一个Directory对象tempDir
- tempDir的构造函数在tfs被初始化之前使用了它,造成未知错误。
- 解决办法:调用返回值为引用的函数。将非局部静态对象转移到函数中,在函数中声明为静态的,然后返回对象的引用。实际上这就是单例模式
class FileSystem{
public:
std::size_t numDisks() const;
};
FileSystem& tfs(){//在此处实现非静态局部对象==>局部静态对象
static FileSystem fs;
return fs;
}
class Directory{
public:
Directory();
};
Directory::Directory(){
std::size_t disks=tfs().numDisks();//调用仿效非局部静态对象的函数
}
Directory& tempDir(){//在此处同样实现 非静态局部对象==>局部静态对象
static Directory td;
return td;
}
参考资料
- 迈耶斯. Effective C++ : 改善程序与设计的55个具体做法 : 55 specific ways to improve your programs and designs[M]. 北京 : 电子工业出版社, 2011