Effective C++ 条款 —— 确定对象在使用前已先被初始化

  • 最佳的处理方法就是:永远在使用对象之前先将其初始化。对于内置类型,你必须手工完成此事。如,

    int x = 0;
    
    double d;
    cin >> d;
    
  • 对于类对象,确保每一个构造函数都将对象的每一个成员初始化。

    • 别混淆了赋值初始化

      class ABEntry {
      public:
          ABEntry(const std::string &name, const std::list<PhoneNumber> &phones) {
          	// 以下这些都是赋值,而不是初始化!!
              theName = name;
              thePhones = phones;
          }
          ...
      };
      

      上述都是赋值,而非初始化!!

      对象的成员变量的初始化 早于 这些成员的 default 构造函数被自动调用 早于 进入类的构造函数的函数体

      而上述做法,它首先调用成员的default构造函数为成员设初值,然后立即再对它们重新赋予新值。

      正确的做法是使用成员初始化列表来初始化对象的每一个成员。

      class ABEntry {
      public:
          ABEntry(const std::string &name, const std::list<PhoneNumber> &phones)
          	:theName(name),
          	 thePhones(phones) {}
          ...
      };
      

      如果成员变量是 const 或 references,则它们就一定需要初始值,而不能被赋值

  • 类对象的成员初始化顺序:base classes 更早于其 derived classes 被初始化,而class的成员变量总是以其声明次序被初始化

  • 不同编译单元内定义的non-local static对象的初始化次序

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

      扫描二维码关注公众号,回复: 5523647 查看本文章
    • 编译单元:指产出单一目标文件的那些源码。

    • 如果某编译单元内的某个non-local static对象的初始化动作使用了另一编译单元内的某个non-local static对象,它所用到的这个对象可能尚未被初始化,因为C++对“定义于不同编译单元内的non-local static对象”的初始化次序并无明确定义。如,

      class FileSystem {
      public:
      	std::size_t numDisks() const;
      	...
      };
      
      extern FileSystem tfs;
      
      class Directory {
      public:
      	Directory();
      };
      
      Directory::Directory() {
      	std::cout << tfs.numDisks() << std::endl;		// 使用 tfs 对象
      }
      
      
      Directory tmpDir;
      

      现在,除非 tfs 在 tmpDir 之前先被初始化,否则 tmpDir 的构造函数将使用尚未被初始化的 tfs 。但 tfs 和 tmpDir 是不同的人于不同的时间在不同的源码文件中建立的,它们是定义于不同编译单元内的 non-local static 对象。如何能够确保 tfs 会在 tmpDir 之前先被初始化呢?

    • 解决办法将每个non-local static对象搬到自己专属的函数内(该对象在此函数内被声明为static),且这些函数返回一个reference指向它所含的对象,然后调用这些函数,而不是直接指涉这些对象。换句话说,将non-local static对象转换为local static对象。其理论基础是:C++保证,函数内的local static对象会在“该函数调用期间”“首次遇上该对象的定义式”时被初始化

      class FileSystem {
      public:
      	std::size_t numDisks() const;
      };
      
      extern FileSystem& tfs();			// 替换 tfs 对象
      
      FileSystem& tfs() {
      	static FileSystem fs;				// 定义并初始化一个 local static 对象
      	return fs;							// 返回该对象的引用
      }
      
      class Directory {
      public:
      	Directory();
      	...
      };
      
      Directory::Directory() {
      	std::cout << tfs().numDisks() << std::endl;		// 改用 tfs()
      }
      
      Directory& tmpDir() {					// 替换 tmpDir 对象
      	static Directory tmp;
      	return tmp;
      }
      
      

猜你喜欢

转载自blog.csdn.net/fcku_88/article/details/88377272