确定对象被使用前已先被初始化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18218335/article/details/84672790

确定对象被使用前已先被初始化

未初始化代表的是不确定

  • 内置类型,必须手工完成初始化

  • 内置类型之外的,构造函数进行初始化

不要混淆了赋值和初始化的概念

对象的成员变量的初始化动作发生在进入构造函数本体之前

  • 使用成员初值表
  • 这个初值表的初始化操作是在构造函数之前的
  • 如果是在构造函数内赋值,此时就是赋值而不是初始化了,因为,此时,某些成员变量的默认构造函数,或者,父类构造函数已经开始执行了,即,它们已经被默认值,初始化一遍了

总是使用成员初始值,且成员初值表需要涵盖所有的成员变量,以免有任何的遗漏

  • 避免存在未初始化的变量

  • const 和 reference 必须进行初始化,即使对于内置类型来说,初始化和赋值的效率是相同的

有时,许多class 有多个构造函数,存在很多成员变量,甚至有很多基类,此时,反复的构造函数可能导致比较繁琐的代码。

  • 可以使用一个通用的私有,初始化函数,来进行一些通用的操作

  • 另外,当,对象的构造函数中涉及的初始化操作,无论是通过初始化、赋值,效果一样好时,可以赋值操作,或,私有初始化函数

  • 当初始化中包含了数据库或文件读入时,将其放入单独的函数中

  • 但,总的来说,尽量使用成员初值表

初始化顺序的问题

C++ 有十分固定的初始化顺序

  • 基类比派生类的构造函数更早的构造
  • class 的成员变量以其初始化的顺序进行初始化
  • 在成员初值列中列出各个成员时,最好总是以其声明次序为次序

不同编译单元内定义的非本地静态对象的初始化次序

  • 静态对象

    • 从被构造出来直到程序终止,都存在
    • 全局对象、位于命名空间作用域内的对象、classes 内、函数内、文件作用域内被声明为static 的对象
    • 函数内的对象被称为本地静态对象、其他的都是非本地静态对象
    • 程序结束时静态对象会被自动销毁,它们的析构函数会在main 结束时自动调用
  • 编译单元

    • 产出单一目标文件的源码
    • 基本上是单一源码文件加上其所含入的头文件
  • 当某编译单元内的某个非本地静态对象的初始化使用了另一个编译单元内的某个非本地静态变量对象,它所用到的这个对象可能尚未被初始化

  • C++ 对于不同编译单元内的非本地静态对象的初始化并无明确定义

  • 解决方法:
    将每个non-local static 对象搬到自己的专属函数内(该对象在此函数内被声明为static)。这些函数返回一个引用指向它所包含的对象,然后用户调用这些函数,而不直接指涉这些对象。------------------------即所谓的单例模式

    • 使用inline 函数,可以更好的,提高这个简短的函数的使用性能
    • 多线程环境下,在整体环境尚处在单线程时,手工调用reference-returning 函数,消除初始化有关的竞速形式

总结

方法

  • 手工初始化内置型non-member 对象
  • 使用成员初值列对对象的所有成分
  • 在”初始化次序不确定性“氛围下加强设计,比如上面的单例模式

原则

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

下面是,确保实验,inline 函数中本地静态对象是同一个对象

#include <iostream>
using namespace std;
class CodeExample
{
public:
    explicit CodeExample(int size);
    ~CodeExample();
private:
    int m_size;
    wchar_t *m_buffer;
};
inline CodeExample& Single()
{
    static CodeExample static_Code(0x10);
    //cout << static_cast<void *> (&static_Code) << endl;
    return static_Code;
}
CodeExample::CodeExample(int size) :m_size(size), m_buffer((wchar_t *)operator new[](m_size))
{
    cout << static_cast<void *>(m_buffer) << endl;
}
CodeExample::~CodeExample()
{
    delete[] m_buffer;
}
void Fun1()
{
    cout << static_cast<void *> (&Single()) << endl;
}
void Fun2()
{
    cout << static_cast<void *> (&Single()) << endl;
}
int main()
{
    Fun1();
    Fun2();
	getchar();
	getchar();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_18218335/article/details/84672790