• 【04】确定对象被使用之前已先被初始化


    1、首先区分初始化和赋值。

      初始化:创建对象时赋给初始值。赋值:擦除对象当前值,并用新值代替。因此,区分初始化和赋值的关键是,看看对象当前是否已经有值了。

    2、创建对象的时候,如果没有初始化,对象的值是什么?

      取决于对象的类型和对象定义的位置。

      a、如果对象是内置类型,定义在方法外,它的值为0,定义在方法内,没有初始化。

      b、如果对象是类类型,无论定义在哪里,都会调用默认构造方法,也就是说,对于类类型的对象,不存在没有初始化的情况。

    3、现在考虑,类中的数据成员,也就是字段。类的构造方法执行两个过程:成员初始化列表和方法内赋值。对于类类型,前者用于初始化,即copy构造;后者用于赋值,即copy赋值。对于内置类型,前者和后者都可用于初始化,如果前者没有初始化,可在后者中初始化。

    4、如果没有在成员初始化列表中显式初始化,出现什么情况?

      a、如果是类类型,隐式初始化,调用默认构造方法;

      b、如果是内置类型,不被初始化,它的取值,按照变量初始化规则进行。它的取值依赖于所属对象的作用域,所属对象是局部对象,不被初始化,所属对象是全局对象,初始化为0。如果内置类型是static字段呢?static字段必须在头文件之外定义(static+const+int是个特殊情况,可以只声明,不定义),定义时没有初始化,取值多少?因为它是类作用域内的全局变量,取值为0。

    5、因此,对于类类型,,在方法内赋值,相当于执行了一次初始化,一次赋值。为了效率,应该在成员初始化列表中初始化。对于内置类型,两种方式等效,为了一致性,也在成员初始化列表中进行。但是,有三种情况必须在初始化列表中进行:a、类类型没有默认构造方法;b、引用;c、const对象。

    6、类中字段的初始化顺序与初始化列表的顺序无关,而是与类定义中的声明顺序保持一致。

    7、static对象可认为包括:全局对象,定义在namespace内的对象,在class内、方法内、以及file内的static对象。根据作用域可分为local static对象和non-local static对象,方法内的static对象时local static对象,其他的static对象是non-local static对象。

    8、现在考虑,不同编译单元中non-local static对象的初始化顺序。C++中,对于不同编译单元的non-local static对象的初始化顺序没有明确定义,也就是说初始化顺序是不确定的。思考,为什么C++不定义,因为做不到。因为C++是单独分别编译,当前编译单元的编译不依赖其他编译单元的编译。

    9、那怎么解决上面的问题呢?

      使用一个方法,方法内部创建一个local static对象,返回这个local static 对象。对于多线程系统,为了保证只有一个local static对象,需要使用加锁机制。

  • 相关阅读:
    浏览器缓存机制
    es6笔记(6) Iterator 和 for...of循环
    es6笔记(3.1)三个点的“...”的作用
    es6笔记(5)Map数据结构
    es6笔记(4) Set数据结构
    SpringBoot事件监听
    SpringBoot入门
    五大常用算法之三贪心算法
    五种常用算法之二:动态规划算法
    五大常用算法之一:分治算法
  • 原文地址:https://www.cnblogs.com/nzbbody/p/3519659.html
Copyright © 2020-2023  润新知