菜鸟资源网站全面焕新升级啦!全新的界面设计,简洁而不失雅致,让您一目了然,轻松上手。我们还对资源分类进行了细致梳理,确保各类资源条理清晰,便于您按需筛选与查找。 立即查看

第六章:确保每个对象在使用前已被初始化,了解C++基本语言特性变量和类型

第六章:确保每个对象在使用前已被初始化,了解C++基本语言特性变量和类型

  关于“将对象初始化”这个问题,C++似乎反复无常。如果你定义一个int变量,编写这样的代码:   在某些语境下x保证会初始化为 0,但在其他语境下却无法保证。如果你编写了这样的代码:   pt的成员变量有时会被初始化(为0),有时候不会...

当前版本

软件大小

软件语言

是否破解

  关于“将对象初始化”这个问题,C++似乎反复无常。如果你定义一个int变量,编写这样的代码:

  int x;

  在某些语境下x保证会初始化为 0,但在其他语境下却无法保证。如果你编写了这样的代码:

  Class CPoint  //二维点数据类
  {
    intmiX;    //二维点的x坐标
    int m_iY;  //二维点的y 坐标
  }
  ...
  CPointpt;   //声明一个点pt

  pt的成员变量有时会被初始化(为0),有时候不会。如果你是来自其他语言阵营的编程人员,那么请注意这点,因为这点颇为重要。

  读取未初始化的对象会导致不确定的行为。在某些情况下,读取未初始化的对象会让你的程序终止运行,但在另外一些情况下会读入一些随机的bits,最终导致不可预知的程序行为。这种现象一般表现为程序可正常执行,但是执行结果有时正确有时错误,无任何规律可言。

  对于“对象的初始化何时一定发生,何时不一定发生”已经有一些规则了,但是不幸的是这些规则都过于复杂,不利于记忆。通常如果你使用的是C++中的 C部分,由于对象的初始化可能会招致运行期的成本,那么对象就不保证会初始化。但对于C++中的非C部分,这个规则就发生变化了,对象一般会发生初始化。这就可以很好地解释为什么数组不会发生初始化,而来自stl的vector 却会发生初始化过程。

  从表面上看,对象在使用前是否会被初始化是无法确定的,而最佳的处理方法是:永远在对象被使用之前将它初始化;对于无任何成员的内置数据类型,必须手动完成初始化。例如:

  int1=5;                              //对int进行手动初始化
  char*pszStr="a c strig”;            // 对指针进行手动初始化

  对于内置类型以外的任何其他成员,初始化的责任落到了对象的构造函数上。其实规则很简单:保证每个对象在构造时初始化该对象的每个成员。

  这个规则很简单,也很容易执行。但这里容易混淆的是赋值和初始化。考虑CPerson 类的构造函数实现如下:

  typedef enum tagSex       //性别枚举类型
  {
    MALE SEX=0,          //MALE SEX表示男性
    FEMALE SEX,          //FEMALE SEX表示女性
  }Sex;
  Class CPerson                  //CPerson类型实现人的描述:名字和性别
  {
    std::string m_strName;          //名字
    Sex     m_sex;                //性别
  CPerson::CPerson(std::string &strName,Sex &sex) // CPerson类赋值型构造函数
  {
    m strName - strName;
    m sex=sex:
  }

  这种实现会导致CPerson 对象带有你期望的值,但这种实现方法并不是一种最佳的实现方法。因为 C++规定对象中成员变量的初始化发生在对象的构造函数之前,所以 CPerson 构造函数中 m strName 和 m sex都不是初始化,而是赋值。

  C++对象的构造函数一个较佳的写法是使用成员初始化列表替换赋值动作:

  CPerson::CPerson(std::string &strName, Sex &sex)
  :m _strName(strName)
  ,m_sex(sex)
  {
  }

  这种构造函数和上一个构造函数最终的结果一样,但是效率更高。

  赋值和列表初始化的区别:

  ●使用赋值初始化对象变量时,在构造函数执行前会调用默认构造函数初始化m_strName 和 m_sex,然后再立刻执行赋值操作。这样默认构造函数所做的一切都因此浪费了。通过初始化列表做法,避免了重复操作。所以第二种实现效率更高。

  ●有些情况下,即使赋值和初始化列表两者效率一样,也得使用初始化列表。如果成员变量是const 或 reference,它们就一定要初始化,而不能被赋值。

  ●由于 C++有着固定的初始化顺序:基类先于子类初始化,class 中的变量总是以变量声明的顺序初始化,和成员初始化列表顺序无关,因此在成员初始化列表中初始化各变量时,最好以声明次序为顺序。

  最后介绍non-local static对象初始化问题。为了说明该问题,考虑设计模式中Singleton 模式的实现方法。

  //CFileSystem 文件系统类声明文件 FileSystem.h
  //文件系统类声明
  Class CFileSystem
  {
  public
  //单例模式示例获得接口
    static CFileSystem *Instance():
    char*GetRootName();//获得文件系统root名称
  };
  // CFileSystem 文件系统类实现文件 FileSystem.cpp
  //单例模式示例获得接口实现
  static CFileSystem*Instance()
    {
    static CFileSystem tfs;
    return &tfs;
  }
  // CFileSystem 单例模式使用文件main.cpp
  CFileSystem *pFileSystem =CFileSystem:Instance):
  char*pszRootName =pFileSystem->GetRootName):

  如果你熟悉多线程编程,你也许已经看出问题了。Instance 静态函数不具有线程安全,在多线程情况下带有不确定性,这就是 non-local static 对象初始化问题。其实在多线程下“等待某事的发生”是一件非常麻烦、代价很高的事情。处理这个麻烦事情的一种做法是:在程序单线程启动阶段手动调用实现 non-local static 对象初始化。

  既然这样,为避免在对象初始化之前过早地使用它们,你需要做3件事情:第一,手动初始化内置类型对象;第二,使用成员初始化列表初始化对象的所有成分;第三,在初始化次序不确定的情况下,加强你的设计,避免类似non-localstatic 对象初始化问题的发生。

  请谨记

  ●为内置类型对象进行手动初始化,因为 C++不保证初始化它们。

  ●构造函数最好使用成员初始化列,而不是在构造函数本体内使用赋值操作。初值列表列出的成员变量,其排列顺序应和它们在class中的声明次序相同。

第六章:确保每个对象在使用前已被初始化,了解C++基本语言特性变量和类型
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

常见问题

  • 如何安装和激活?

    每款软件会附带有安装教程,您打开安装包一目了然

  • 程序是否已损坏?文件损坏?还是其他错误?

    有错误问题,请您参考:https://www.xxx.com/error

  • 如何更新?正式激活后会发生什么情况?

    除非安装说明中另有说明,否则官方更新可能会导致无法激活。 要从本网站更新软件,您需要在此处下载此软件的新版本(如果可用),并将其安装在计算机上安装的版本之上(替换)。在这种情况下,您将保存此软件的激活和设置。

  • 如何下载?链接不起作用?

    我们使用百度网盘,132云盘和微软网盘,除了百度网盘,其他两款不限速,如果链接失效,请您联系客服处理

  • 已发布更新。我什么时候升级我的版本?

    所有软件如有更新,我们第一时间推送,视自己情况更新使用

  • 如何更改语言?

    打开“系统偏好设置”->“通用>语言和地区”->应用程序-“+”。 选择应用和语言。此方法适用于大多数应用程序。 Adobe 产品中的语言通常是在产品本身的安装阶段选择的。 游戏中的语言通常会在游戏本身的设置中发生变化。

  • 如何删除软件?

    有很多选择。最简单的方法是使用特殊的实用程序来卸载应用程序,例如App Cleaner Uninstaller 要删除 Adobe 产品,请使用 Creative Cloud Cleaner Tool

  • 需要远程帮助吗?

    网站已开通永久会员的可享受免费远程,如果非永久会员,远程安装另外收费

给TA打赏
共{{data.count}}人
人已打赏
技术教程

第五章:计算机是如何存储变量的,了解C++基本语言特性变量和类型

2024-2-14 10:57:00

技术教程

第七章:局部变量和全局变量的差别,了解C++基本语言特性变量和类型

2024-2-16 11:22:00

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧