条款四 确定对象被使用前已被初始化
一、未初始化的危害
使用未初始化的值会导致不明确的行为
二、内置类型的初始化
对于内置的数据类型(char,int,float,double等),在使用前必须进行初始化。
构造函数
对于class来说,在使用对象之前,必须使用构造函数对成员变量进行初始化
但是需要注意赋值和初始化的区别
构造函数中的赋值操作(非初始化)
例如下面的构造函数中,对成员变量的都不是初始化,而是赋值操作
class PhontNumber{};
class ABEntry
{
public:
ABEntry(const std::string& name, const std::strinf& address, const std::list<PhontNumber>& phones);
private:
std::string theName;
std::string theAddress;
std::list<PhontNumber> thePhones;
int numTimesConsulted;
}
ABEntry::ABEntry(const std::string& name, const std::strinf& address, const std::list<PhontNumber>& phones)
{
theName = name;
theAddress = address;
thePhones = phones;
numTimeConsulted = 0;
}
成员初始化列表(真正的成员变量初始化)
如果想要对成员进行初始化,应该是在构造函数的成员初始化列表对成员数据进行初始化
class PhontNumber {};
class ABEntry
{
public:
//成员初始化列表初始化:真正的初始化
ABEntry(const std::string& name, const std::string& address,
const std::list<PhontNumber>& phones)
:theName(name), theAddress(address), thePhones(phones), numTimesConsulted(0)
{}
private:
std::string theName;
std::string theAddress;
std::list<PhontNumber> thePhones;
int numTimesConsulted;
};
为什么成员初始化列表比普通赋值效率高
在构造函数内对数据成员赋值而言效率更低,因为它们先需要调用class的默认构造函数对成员数据进行默认的初始化,然后再调用各个成员的拷贝构造函数来进行复制
成员初始化列表:成员初始化列表是在执行构造函数体前运行的代码,因此它们是真正的对数据成员进行初始化
成员初始化顺序
越在前面的成员变量越先被初始化,与成员变量的定义顺序无关
静态对象初始化问题
静态对象的声明周期从定义开始,知道程序结束为止
*静态成员分为哪几类?
①非局部的静态对象:全局静态对象、定义与namespace作用域内的对象、class的静态成员。
②局部的静态对象:函数内部的局部静态变量
本文主要探讨在不同编译单元之间定义“非局部的静态对象”的初始化顺序问题
如现在有一个FileSystem类,它类似一个文件系统,定义如下
class FileSystem
{
public:
std::size_t numDisks()const;
};
extern FileSystem tfs;
现在客户端程序在Directiry.h中建立Directory类用来处理文件系统内的目录
#include "FileSystem.h"
class Directory
{
public:
Directory();
}
Directory::Directory()
{
std::size_t disks = tfs.numDisks();
}
// 现在客户在主程序中创建一个对象来放置临时文件
Directory tempDir;
这里就会出现问题:如果要使用tempDir,必须保证tfs对象已被初始化,但是tfs对象与tempDir对象是出于不同编译单元之间的对象,那怎样才能保证tfs在tempDir使用之前已经被初始化了呢?答案是没有这种方法可以确保。
对于上述问题的解决方法:
将需要用到的非局部静态对象封装到一个函数内,对象在函数内部被声明为static,然后函数返回一个指向这个对象的引用。用户之后调用这些函数,而不是直接调用这个对象。此处非局部静态对象被局部对象替换了。这在设计模式中,是Singleton模式的一种常见方法。
这种手法保证:函数内的局部静态对象会在“该函数被调用期间”被初始化
class FileSystem
{
public:
std::size_t numDisks()const;
}
FileSystem& tfs()
{
static FileSystem tfs;
return fs;
}
更改Directory.h文章来源:https://www.toymoban.com/news/detail-743763.html
#include "FileSystem.h"
class Directory
{
public:
Directory();
};
Directory::Directory()
{
std::size_t disks = tfs.numDisks();
}
Directory& tempDir()
{
static Directory td;
return td;
}
因此,为了避免跨编译单元之间初始化次序的问题,请用局部静态对象替换非局部静态对象文章来源地址https://www.toymoban.com/news/detail-743763.html
到了这里,关于Effective C++ 条款四的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!