永远在使用对象之前先将它初始化。对于无任何成员的内置类型,你必须手工完成此事。

至于内置类型以外的任何其他东西,初始化责任落在构造函数身上。规则很简单:确保每一个构造函数都将对象的每一个成员初始化。

构造函数成员初始化列表:
这里有一个规则:总是在初始化列表中列出所有成员变量,即使有的成员变量是内置类型(内置类型的初始化和赋值成本相同)。

成员初始化顺序
base classes 早于 derived classes 被初始化,class 的成员变量总是以其声明次序被初始化


一个编译单元内定义的”non-local static对象“的初始化次序

static 对象,其寿命从被构造出来知道程序结束为止。
static 对象包括 global 对象、定义于 namespace 作用域内的对象、在class内、在函数内、以及在file 作用域内被声明为 static 的对象。
函数内的 static 对象称为 local static 对象,其他的称为 non-local static 对象。
程序结束时 static对象会被自动销毁。

编译单元是指产出单一目标文件的那些源码。基本上是单一源文件加上其所含入的头文件。

如果某个编译单元内的 non-local static 对象的初始化动作使用了另一个编译单元内的某个 non-local static 对象,他所用到的这个对象可能尚未被初始化。

举个实例加以理解:

//file1: Filesystem.cpp
//
class FileSystem{
public:
std:size_t numDisks() const
}; extern FileSystem tfs; //file2:Directory.cpp
//
class Directory{
public:
Directory(params);
}; Directory::Directory(params)
{
std::size_t disks = tfs.numDisks(); //使用 tfs 对象
} int main()
{
Directory tempDir( params );
} //这个时候初始化的重要性显现出来了,tfs必须在tempdir之前被初始化,否则tempDir的构造函数就会用到尚未初始化的tfs。
//但是C++对于不同编译单元内的 non-local static对象的初始化相对次序并无明确定义。
//为了消除这个问题:
//采用 设计模式中的 Singleton 模式的一个常见实现手法:将每个 non-local static 对象搬到自己的专属函数内(该对象在此函数内被声明为static)
//
//这个手法的基础就是:C++ 保证,函数内的 local static对象会在“该函数被调用期间”“首次遇上该对象之定义式”时被初始化,这样就保证你所获得的reference将指向一个历经初始化的对象
//
//将此技术实施于 tfs 和 tempDir 身上:
//file1: Filesystem.cpp
//
class Filesystem { ... }; //同前
FileSystem& tfs()
{
static FileSystem fs;
return fs;
} //file2:Directory.cpp
class Directory{ ... };
Directory::Directory( params )
{
std::size_t disks = tfs().numDisks();
} Directory& tempDir()
{
static Directory td;
return td;
}

【请记住:】

  • 为内置类型对象进行手工初始化,因为 C++ 不保证初始化它们。
  • 构造函数最好使用成员初始化列表,而不要在构造函数本体内使用赋值操作。
  • 构造函数初始化列表中的成员变量排列次序应该和他们在 class 中的声明次序相同。
  • 为免除 ”跨编译单元值初始化次序“问题,请以 local static 对象替换 non-local static 对象。

【Effective C++ 读书笔记】条款04:确定对象使用前已先被初始化的更多相关文章

  1. effective C++ 读书笔记 条款14 以对象管理资源

    如果我们使用一个投资行为的程序库: #include "stdafx.h" #include <iostream> #include <memory> us ...

  2. Effective C++学习笔记 条款04:确定对象被使用前已先被初始化

    一.为内置类型对象进行手工初始化,因为C++不保证初始化它们. 二.对象初始化数据成员是在进入构造函数用户编写代码前完成,要想对数据成员指定初始化值,那就必须使用初始化列表. class A { pu ...

  3. effective C++ 读书笔记 条款08

    条款08  别让异常逃离析构函数: 假设在析构函数其中发生了异常,程序可能会过早结束或者导致不明白行为(异常从析构函数传播出去) 看代码: #include <iostream> usin ...

  4. effective C++ 读书笔记 条款11

    条款11: 在operator= 中处理"自我赋值" 在实现operator=时考虑自我赋值是必要的就像 x=y .我们不知道变量x与y代表的值是否为同一个值(把x和y说成是一个指 ...

  5. Effective Java2读书笔记-创建和销毁对象(三)

    第5条:避免创建不必要的对象 本条主要讲的是一些反面教材,希望大家引以为鉴. ①无意中使用自动装箱导致多创建对象. public class Sum { public static void main ...

  6. Effective Java2读书笔记-创建和销毁对象(一)

    第1条:考虑用静态工厂方法代替构造器 通常情况下,我们创建一个对象采取new的形式,但是还有一种方法也是经常使用到的,它的名称叫做静态工厂方法. 例如,java中基本类型boolean的包装类Bool ...

  7. 《Effective C++》——条款04:确定对象使用前已先被初始化

    读取未初始化的值会导致不明确的行为.在某些平台上,仅仅只是读取未初始化的值,就可能让你的程序终止运行.更可能的情况是读入一些“半随机”bits,污染了正在进行读取动作的那个对象,最终导致不可预知的程序 ...

  8. Effective Java读书笔记--创建和销毁对象

    1.优先考虑用静态工厂方法代替构造器2.遇到多个构造器参数时要考虑使用构建器Builder解决参数过多,不可变类型.私有构造方法,静态类的构造方法提供必要参数,剩下可选.new xxx.build() ...

  9. Effective Java2读书笔记-创建和销毁对象(四)

    第7条:避免使用终结方法 这一条讲的简直是不知所云.先简单记下来其中说出的几条: ①显式终止方法的典型例子有InputStream.OutputStream和java.sql.Connection上的 ...

随机推荐

  1. C#本期本周的算法

    C#根据当前时间获取,本周,本月,本季度等时间段 DateTime dt = DateTime.Now; //当前时间 DateTime startWeek = dt.AddDays( - Conve ...

  2. jquery常用属性与方法

    1..css( )给指定的样式设置样式值: 2..attr(attributeName,value) /.removeAttr(attributeName);给指定的属性设置值 / 清除所有匹配的元素 ...

  3. node-sass 安装报错解决办法

    npm install安装node-sass时出现以下问题: Cannot download https://github.com/sass/node-sass/releases/download/v ...

  4. document.URL 和 windows.location.href的区别

    1. 从输出结果上,document.URL 和 windows.location.href 没有区别.2. 非要说区别的话,你只可以读取document.URL的值,不能修改它.windows.lo ...

  5. Miner3D 数据分析软件

    现在,越来越多的专业人士愿意选择Miner3D来帮助他们进行快速高效的智能决策,因为它是一个功能强大.专业性强.海量数据存储能力.三维可视化效果逼真的数据分析解决工具.Miner3D凭借出色的图形质量 ...

  6. Implementation with Java

    Implementation with Java From:http://jcsc.sourceforge.net In general, follow the Sun coding conventi ...

  7. kubernetes组件helm

    1.安装helm Helm由客户端helm命令行工具和服务端tiller组成,Helm的安装十分简单. 下载helm命令行工具到master节点node1的/usr/local/bin下(只需要在其中 ...

  8. Arduino-串口函数Serial

    串口是Arduino与其它设备进行通信的接口,我们需要很好的掌握它的使用.Arduino串口使用相关的函数共有10个(随着版本的升级,新版本加入了更多,具体请参见官网:http://www.ardui ...

  9. 如何创建一个新浪微博应用以及获得Access token

    前提条件是您得先有一个新浪微博帐号. 打开网页http://open.weibo.com/wiki/%E9%A6%96%E9%A1%B5 点击新手引导->开发者页面: 会自动跳转到页面:http ...

  10. 22个必须知道的css技巧

    1.改变选中文字的背景和颜色 ::selection{ /* Safari and Opera */ background:#c3effd; color:#000; } ::-moz-selectio ...