条款04:确定对象被使用前已先被初始化

本文探讨了在编程中读取未初始化值可能导致的问题,提倡始终初始化对象。讲解了内置类型和成员变量的初始化方法,以及如何处理全局静态对象初始化的不确定性。通过实例演示了正确的初始化方式和最佳实践。

读取未初始化的值会导致不明确的行为。在某些平台上,仅仅只是读取未初始化的值,就可以能让你的程序终止运行。更可能的情况时读入一些“半随机”bit,污染了正在进行读取动作的那个对象,最终导致不可预测的程序行为,以及许多令人不愉快的调试过程。

最佳的处理办法:永远在使用对象之前先将它初始化


一、内置类型初始化

  • 对于无任何成员的内置类型,必须手工完成此事,例如:

    int x = 0;
    const char* text = "Hello World";
    
    double d;
    std::cin >> d;
    

二、成员变量初始化

  • 内置类型以外的任何其他东西,初始化的责任由构造函数完成,确保每一个构造函数都将对象的每一个成员初始化,但不要混淆赋值和初始化:

    • 赋值(伪初始化)

      class Widget 
      {
      public:
          Widget(const std::string& name, const int& number);
              
      private:
          std::string thename;
          int thenumber;
          
          
      };
      
      Widget::Widget(const char& name, const int& number)
      {
          this->thenumber = name;
          this->thenumber = number;
      }
      
    • 初始化

      class Widget 
      {
      public:
          Widget(const std::string& name, const int& number);
              
      private:
          std::string thename;
          int thenumber;
          
          
      };
      
      Widget::Widget(const char& name, const int& number) 
          :thename(name),
      	 thenumber(number)
      {
          
      }
      
    • 初始化版本的构造函数和赋值版本的构造函数最终结果相同,但通常效率较高。

      • 基于赋值的版本首先调用default构造函数为成员变量设初值,然后立刻再对它们赋予新值,default构造函数的一切作为因此浪费了;
      • 基于初始化的版本针对各个成员变量而设的实参,被拿去作为各成员变量之构造函数的实参,以实参为初值进行copy构造;
      • 对于大多数类型而言,比起先调用default构造函数然后再调用赋值操作符,只调用一次复制构造函数时比较高效的,有时甚至高效得多。

注意

  • 存在多个构造函数,重复的初始化列表很烦躁,可以把一部分成员变量放在函数中(一般时privete),用赋值的方法给初值;
  • 初始化列表列出的成员变量,其排列次序应该和它们在class中的声明次序相同;

三、初始化次序不确定的初始化

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

为了确保使用的这个对象已被初始化,可以采用如下方法:

将每个全局static对象搬到自己的专属函数内(该对象在此函数内被声明为static),这些函数返回一个reference指向它所含的对象。然后用户调用这些函数,而不直接指涉这些对象(其实就是Singleton模式的常见实现手法);

class Widget 
{
public:
    Widget(const std::string& name, const int& number);
    Widget& wd()
    {
    	static Widget wd;
    	return wd;
	}                
};

总结

  • 手工初始化内置型对象;
  • 使用成员初始化表初始化对象的所有成员变量;
  • 再“初始化次序不确定性”的情况下,使用局部static对象替换全局static对象;
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贝勒里恩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值