确定一个对象在使用前已经被初始化

C++确定对象被使用前已先被初始化 确定对象被使用前已先被初始化读取未初始化对象的后果按对象的类型划分按对象的作用域与生命周期划分 读取未初始化对象的后果 读取未被初始化的值会导致不明确的行为。在某些平台上,仅仅只是读取未初始化的值就可能让程序终止,更可能的情况是读入一些“半随机”bits,污染了正在进行读取动作的那个对象,最终导致不可预知的程序行为,以及许多令人不愉快的调试过程 按对象的类型划分 •对于内置类型的对象:永远在使用前初始化 •类类型的对象:初始化责任落在构造函数身上 –效率上的问题: •类类型成员的初始化动作发生在构造函数本体 阅读详情
C++ 看上去在对象的初始化方面变化无常。例如,如果你这样做,

int x;

在某些情形下,x 会被初始化(0),但是在其它情形下,也可能没有。如果你这样做,

class Point {

  int x, y;

};
...
Point p;

p 的数据成员有时会被初始化(0),但有时没有。如果你从一个不存在未初始化对象的语言来到 C++,请注意这个问题,因为它非常重要。

读取一个未初始化的值会引起未定义行为。在一些平台上,读一个未初始化的值会引起程序中止,更可能的情况是得到一个你所读的那个位置上的随机值,最终导致不可预测的程序行为和恼人的调试。

现在,有一些关于什么时候进行对象的初始化什么时候不进行的规则的描述。不幸的是,这些规则很复杂——我觉得它复杂得无法记住。通常,如果你使用 C++ 的 C 部分(参见 Item 1),而且初始化可能会花费一些运行时间,它就不一定会进行。如果你使用 C++ 的 non-C 部分,事情会有些变化。这就是为什么一个数组(C++ 的 C 部分)不能确保它的元素被初始化,但是一个 vector(C++ 的 STL 部分)就能够确保。

处理这种表面上看起来不确定的事情的最好方法就是总是在使用之前初始化你的对象。对于内建类型的非成员对象,需要你手动做这件事。例如:

int x = 0;                                // manual initialization of an int

const char * text = "A C-style string";   // manual initialization of a
                                          // pointer (see also Item 3)

double d;                                 // "initialization" by reading from

std::cin >> d;                            // an input stream

除此之外的几乎全部情况,初始化的重任就落到了构造函数的身上。这里的规则很简单:确保所有的构造函数都初始化了对象中的每一样东西。

这个规则很容易遵守,但重要的是不要把赋值和初始化搞混。考虑下面这个表现一个通讯录条目的类的构造函数:

class PhoneNumber { ... };

class ABEntry {                       // ABEntry = "Address Book Entry"

public:

  ABEntry(const std::string& name, const std::string& address,
          const std::list<PhoneNumber>& phones);

private:

  std::string theName;

  std::string theAddress;

  std::list<PhoneNumber> thePhones;

  int num TimesConsulted;

};

ABEntry::ABEntry(const std::string& name, const std::string& address,
                 const std::list<PhoneNumber>& phones)

{

  theName = name;                       // these are all assignments,

  theAddress = address;                 // not initializations

  thePhones = phones;

  numTimesConsulted = 0;

}

这样做虽然使得 ABEntry 具有了你所期待的值,但还不是最好的做法。C++ 的规则规定数据成员的初始化在进入构造函数的函数体之前进行。在 ABEntry 的构造函数内,theName,theAddress 和 thePhones 不是被初始化,而是被赋值。初始化进行得更早——在进入 ABEntry 的构造函数的函数体之前,他们的缺省的构造函数已经被调用。但不包括 numTimesConsulted,因为它是内建类型。不能保证它在被复制之前被初始化。

一个更好的方法是用成员初始化列表(member initialization list)来代替赋值:

ABEntry::ABEntry(const std::string& name, const std::string& address,
                 const std::list<PhoneNumber>& phones)

: theName(name),
  theAddress(address),                  // these are now all initializations
  thePhones(phones),
  numTimesConsulted(0)

{}                                      // the ctor body is now empty

这个构造函数的最终结果和前面那个相同,但是通常它有更高的效率。基于赋值的版本会首先调用缺省的构造函数初始化 theName,theAddress 和 thePhones,然而很快又用新的值覆盖了缺省构造函数的值。缺省构造函数所做的工作被浪费了。而成员初始化列表的方法避免了这个问题,因为初始化列表中的参数就可以作为各种数据成员的构造函数所使用的参数。在这种情况下,theName 从 name 中拷贝构造,theAddress 从 address 中拷贝构造,thePhones 从 phones 中拷贝构造。对于大多数类型来说,只调用一次拷贝构造函数的效率比先调用一次缺省构造函数再调用一次拷贝赋值运算符的效率要高(有时会高很多)。

对于 numTimesConsulted 这样的内建数据类型,初始化和复制没有什么不同,但为了统一性,最好是通过成员初始化列表来初始化每一件东西。类似地,当你只想调用一个数据成员的缺省构造函数时也可以使用成员初始化列表,只是不指定参数而已。例如,如果 ABEntry 有一个无参数的构造函数,它可以像这样实现:

ABEntry::ABEntry()
:theName(),                         // call theName''s default ctor;
theAddress(),                      // do the same for theAddress;
thePhones(),                       // and for thePhones;
numTimesConsulted(0)               // but explicitly initialize

{}                                  // numTimesConsulted to zero

因为对于那些在成员初始化列表中没有初始化的用户自定义类型的数据成员,编译器会自动调用其缺省构造函数,所以一些程序员会认为上面的方法有些过分。这也不难理解,但是一个方针是:在初始化列表中总是列出每一个数据成员,这就可以避免一旦发生疏漏就必须回忆起可能是哪一个数据成员没有被初始化。例如,因为 numTimesConsulted 是一个内建类型,如果将它从成员初始化列表中删除,就为未定义行为打开了方便之门。

有时,即使是内建类型,初始化列表也必须使用。比如,数据成员是必须被初始化的const或引用,他们不能被赋值(参见 Item 5)。为了避免记忆什么时候数据成员必须在成员初始化列表中初始化,而什么时候又是可选的,最简单的方法就是总是使用初始化列表。它有时是必须的,而且它通常都比赋值更有效率。

很多类有多个构造函数,而每一个构造函数都有自己的成员初始化列表。如果有很多数据成员和/或基类,成倍增加的初始化列表的存在引起郁闷的重复(在列表中)和厌烦(在程序员中)。在这种情况下,不能不讲道理地从列表中删除那些赋值和初始化一样工作的数据成员,而是将赋值移到一个单独的(当然是私有的)函数中,以供每个构造函数调用。这个方法对于那些真正的初值是从文件中读入或从数据库中检索出来的数据成员没有特别的帮助。通常情况下,无论如何,真正的成员初始化(通过一个初始化列表)比通过赋值来进行初始化更可取。

C++ 并非变幻莫测的方面是一个对象的数据被初始化的顺序。这个顺序总是相同的:基类的初始化在派生类之前(参见 Item 12),在一个类内部,数据成员按照他们被声明的顺序进行初始化。例如,在 ABEntry 中,theName 总是首先被初始化,theAddress 是第二个,thePhones 第三,numTimesConsulted 最后。即使在成员初始化列表中的顺序与此不同(不幸合法),这个顺序也不会变。为了避免读者混淆以及一些模糊不清的行为引起错误的可能性,初始化列表中列出的成员的顺序应该总是与它们在类中被声明的顺序保持一致。

一旦明确处理了内建类型的非成员对象的初始化,而且确信你的构造函数使用成员初始化列表初始化了它的基类和数据成员,那就只剩下一件事情需要费心了。那就是——先深呼吸——定义在不同转换单元(translation units)中的非局部静态(non-local static)对象的初始化顺序。

让我们一片一片地把这个词组拆开。

一个静态对象的生存期是从它创建开始直到程序结束。基于堆栈的对象就被排除了。包括全局对象,命名空间内定义的对象,类内声明为静态的对象,函数内声明为静态的对象和在文件范围内被声明为静态的对象。函数内的静态对象以局部静态对象(因为它局部于函数)为人所知,其他各种静态对象以非局部静态对象为人所知。程序结束时静态对象会自动销毁,也就是当主程序停止执行时会自动调用它的析构函数。

一个转换单元(translation units)可以形成一个单独的目标文件(object file)。基本上是一个单独的源文件,加上它全部的 #include 文件。

我们关心的问题是这样的:至少有两个分别编译的源文件,每一个中都至少包含一个非局部静态对象(也就是说,全局的,命名空间范围的,类内静态的或文件范围的对象)。实际的问题是这样的:如果其中一个转换单元内的一个非局部静态变量的初始化用到另一个转换单元内的非局部静态变量,它所用到的对象可能没有被初始化,因为定义在不同转换单元内的非局部静态对象的初始化顺序是没有定义的。

让一个例子来帮助我们。假设你有一个 FileSystem 类,可以使一个在互联网上的文件看起来就像在本地。因为你的类认为世界只有一个文件系统,你可以在全局或命名空间范围内创建一个特殊的对象来代表这个唯一的文件系统:

class FileSystem {                    // from your library

public:
  ...
  std::size_t numDisks() const;       // one of many member functions
  ...
};

extern FileSystem tfs;                // object for clients to use;
                                      // "tfs" = "the file system"

一个 FileSystem 对象自然没有太大作用,为了使用这个 FileSystem 对象,在创建它之前,还有很多事情要做。

现在假设一些客户为一个文件系统中的目录创建了一个类,他们的类自然会用到这个 FileSystem 对象。

class Directory {                       // created by library client

public:

   Directory( params );
  ...
};

Directory::Directory( params )

{
  ...
  std::size_t disks = tfs.numDisks();   // use the tfs object
  ...
}

更进一步,假设这个客户决定为临时文件创建一个单独的目录对象:

Directory tempDir( params );           // directory for temporary files

现在初始化的顺序显然变得重要了:除非 tfs 在 tempDir 之前初始化,否则,tempDir 的构造函数就会在 tfs 被初始化之前试图使用它。但是,tfs 和 tempDir 是被不同的人在不同的时间不同的源文件中创建的——这就是定义在不同转换单元(translation units)中的非局部静态(non-local static)对象。你怎么能确信 tfs 一定会在 tempDir 之前被初始化呢?

你不能。重申一遍,定义在不同转换单元中的非局部静态对象的初始化的相关顺序是未定义的。这是有原因的。决定非局部静态对象的“恰当的”初始化顺序是困难的,非常困难,以至于是一个无法完成的任务。在最常见的形式下——多个转换单元和非局部静态变量通常通过隐式模板实例化产生(这本身可能也是由于隐式模板实例化引起的)——不仅不可能确定一个正确的初始化顺序,甚至不值得去寻找可能确定正确顺序的特殊情况。

幸运的是,一个小的设计变更会从根本上解决这个问题。全部要做的就是将非局部静态对象移到他自己的函数中,在那里它被声明为静态。这个函数返回它所包含的对象的引用。客户可以调用这些函数来代替直接涉及到那些对象。换一种说法,就是用局部静态对象取代非局部静态对象。(设计模式迷们会认出这是 Singleton 模式的普通实现)。

这个方法建立在 C++ 保证局部静态对象的初始化发生在因为调用那个函数而第一次遇到那个对象的定义的时候。所以,如果你用调用返回局部静态对象的引用的函数的方法取代直接访问非局部静态对象的方法,你将确保你取回的引用引向已初始化的对象。作为一份额外收获,如果你从不调用这样一个仿效非局部静态对象的函数,你就不会付出创建和销毁这个对象的代价,而一个真正的非局部静态对象则不会有这样的效果。

以下就是这项技术在 tfs 和 tempDir 上的应用:

class FileSystem { ... };           // as before

FileSystem& tfs()                   // this replaces the tfs object; it could be

{                                   // static in the FileSystem class

  static FileSystem fs;             // define and initialize a local static object

  return fs;                        // return a reference to it

}

class Directory { ... };            // as before

Directory::Directory( params )      // as before, except references to tfs are

{                                   // now to tfs()
  ...
  std::size_t disks = tfs().numDisks();
  ...
}

Directory& tempDir()                // this replaces the tempDir object; it

{                                   // could be static in the Directory class

  static Directory td;              // define/initialize local static object

  return td;                        // return reference to it

}

这个改良系统的客户依然可以按照他们已经习惯的方法编程,只是他们现在应该用 tfs() 和 tempDir() 来代替 tfs 和 tempDir。也就是说,他们应该使用函数返回的对象引用来代替使用对象自身。

按照以下步骤来写返回引用的函数总是很简单:在第 1 行定义并初始化一个局部静态对象,在第 2 行返回它。这样的简单使它们成为内联函数的极好的候选者,特别是在它们经常被调用的时候(参见 Item 30)。在另一方面,这些函数包含静态对象的事实使它们在多线程系统中会出现问题。更进一步,任何种类的 non-const static 对象——局部的和非局部的——在多线程存在的场合都会发生麻烦。解决这个麻烦的方法之一是在程序的单线程启动部分手动调用所有的返回引用的函数。以此来避免与初始化相关的混乱条件。

当然,用返回引用的函数来防止初始化顺序问题的想法依赖于你的对象在它第一次出现的地方有一个合理的初始化顺序。如果你有一个系统要求对象 A 必须在对象 B 之前初始化,但是 A 的初始化又依赖于 B 已经被初始化,你将遇到问题,坦白地讲,你遇到大麻烦了。如果你避开了这种病态的境遇,这里描述的方法会很好地为你服务,至少在单线程应用程序中是这样。

避免在初始化之前使用对象,你只需要做三件事。首先,手动初始化内建类型的非成员对象。第二,使用成员初始化列表初始化对象的每个部分。最后,围绕定义在不同的转换单元中的非局部静态变量初始化顺序不确定的问题进行设计。

Things to Remember
手动初始化内建类型的对象,因为 C++ 只在某些时候才会自己初始化它们。
在构造函数中,用成员初始化列表代替函数体中的赋值。初始化列表中数据成员的排列顺序要与他们被声明的顺序相同。
通过用局部静态变量代替非局部静态变量来避免不同转换单元的初始化顺序问题。
 
迈德威视相机调用( 基于 Linux系统+ OpenCV ) 迈德威视相机调用( 基于 Linux系统+ OpenCV )前言一、登录迈德威视官网,下载官方SDK二、代码调用与视频帧处理( 基于 OpenCV )总结 前言     此博客记录了迈德威视工业相机在 Linux 系统下的代码调用及其环境配置,通过 OpenCV 对视频帧进行处理。   一、登录迈德威视官网,下载官方SDK      迈德威视官网 : http://www.mindvision.com.cn/     1. 进入官网后,在服务支持中选择软件下载。    2. 选择Linux系统S. 阅读详情

相关推荐

基于稀疏表示字典学习的图像超分辨率-杨建超论文解析

文章:《Image Super-Resolution via Sparse Representation》 作者:杨建超 信号稀疏的定义: 令字典D的原子个数M,信号维度为N,则有以下三种关系: M = N时,D为完备的; M > N时,D为冗余的; M>>N时, D为过完备的。 图解如下: 借鉴了压缩感知的思想,通过对大量低分辨率图像和高分辨...

ycc18829026593的博客 7637

Effective C++ ——初始化

初始化,一个老生常谈的话题,你都掌握了吗? 1.初始化和赋值 不是一个概念,记住这点很重要 2.内置类型的初始化 确保在使用之前先初始化,定义时即初始化,避免很多诡异的问题出现。 3.非内置类型的初始化 构造函数负责初始化工作,对于类成员变量,初始化工作发生在进入构造函数之前,在构造函数内部进行的都是赋值动作,不是初始化。 4.使用初始化列表进行初始化class

michael019的博客 418

新手必看:如何用R/qtl快速完成QTL定位分析(附实战代码)

本文为新手提供了使用R/qtl进行QTL定位分析的完整实战指南。内容涵盖从环境搭建、数据准备与清洗,到核心分析流程(包括遗传图谱计算、单QTL扫描、置换检验确定阈值)以及进阶结果可视化的全步骤。通过清晰的代码示例,帮助读者快速掌握这一数量遗传学关键分析技术,实现从数据到QTL峰值的完整分析闭环。

y7z8a的博客 498

C++string字符串初始化与使用

字符串 C风格字符串 C-风格字符串具有 一种特殊的性质:以空字符(null character)结尾,空字符被写作\0, 其ASCII码为0,用来标记字符串的结尾。例如, char dog[8] = {'b', 'e', 'a', 'u', 'x', ' ', 'i', 'i'}; // 不是字符串 char cat[8] = {'f', 'a', 't', 'e', 's', 's', 'a', '\0'}; // 是字符串 更好的初始画字符串的方法:使用字符串常量 char bird[11] =

京龙 7551

Parrot OS最新安装教程

Parrot OS和Kali Linux一样是一个基于 Debian 的免费开源 Linux 发行版,适合安全专家、开发人员、以及关心隐私的人。相较于Kali,Parrot OS属于轻量级,对于硬件的要求无需很高,目前版本已更新到6.3。通过按照本教程的方法,能够成功安装Parrot OS。

🦸💻冰草花生酱提醒您“请记得检查所有电子设备的最后登录时间哦⏰🔍” 4410

【知识分享】IBIS 建模指南 03

本文介绍了差分缓冲器的数据提取方法,重点分析了差分系统与单端系统的核心差异。文章详细阐述了差分接收机和驱动器的结构特点、工作原理及建模方法,指出全差分结构具有优异的电源噪声抑制能力。针对IBIS建模规范,作者提出了三维I-V曲面数据提取技术,并介绍了共模/差模电流分离、片上端接处理以及V-T表生成的解决方案。文章还探讨了差分电容(C_diff)的测量方法和数据简化策略,为复杂差分缓冲器的精确建模提供了系统化的技术路径。

一只豌豆象的博客 1281

对象初始化

第二章 iOS之初始化方法的重写我们来看看如果不初始化会出现怎样的结果:类的接口: 类的实现: 测试: 结果: 这里就看出来初始化的重要性了。类的接口和实现部分都和上边相同,给出测试部分: 结果: 类的接口: 类的实现: 测试部分: 结果: 我们发现,这两个对象在调用init方法时,会自动为对象赋值。因为我们重写了init方法,我们这里使用的init方法不在是NSObject提供的,而是我们重写的。在我们调用被重写的init方法后,会自动给对象赋值。...............

weixin_61196797的博客 2532

171、运动控制中的标定:摩擦力与死区补偿标定

摘要(149字) 运动控制系统中的摩擦力与死区补偿是提升精度的关键。摩擦力分为静摩擦、库仑摩擦和粘滞摩擦,其中Stribeck效应是低速抖动的主因;死区则表现为控制信号的无效区间。有效标定方法包括恒速测试(摩擦力)和斜坡响应法(死区)。补偿策略需采用分段前馈和动态调整,避免过度补偿导致振荡。实践中要注意机械状态检查、补偿量限幅,并定期重新标定。硬件升级配合算法补偿才能实现最优控制,标定工作应优先于PID参数调整。

m0_50546716的博客 226

对象的初始化过程及其深入理解

一、什么是一个类 在Java语言里面,类用class描述,拥有变量和函数。没有提供get或set方法的变量称之为字段。有get或者set的任意方法或全部方法的字段称之为属性。所有的类都继承自Object类,并且继承了Object类提供的class属性。 类和对象的关系,简单说: 类可以看成一类对象的模板,对象可以看成该类的一个具体实例。 二、子类...

大宇的博客,欢迎访问 1万+

【人工智能时代】-什么是MCP?本地如何开发MCP Server

MCP(Model Context Protocol)全称模型上下文协议,是由 Anthropic 推出的一种开放标准,旨在统一大型语言模型(LLM)与外部数据源和工具之间的通信协议。掌握更多的信息控制更多的工具在没有联网搜索之前,大模型的数据来源只有训练数据的时候以及推理我们告诉他的东西。所以后来的rag、知识库都是让AI掌握更多的信息,而MCP的出现是为了让大模型控制更多的工具,赋予更多能力。在本篇文章中,基于 Python 完成了一个简单的 MCP Server 的开发。

xiaoli8748的专栏 1984

【保姆级教程】YOLOv8_OBB旋转目标检测:训练自己的数据集

【保姆级教程】YOLOv8_OBB旋转目标检测:训练自己的数据集

m0_51579041的博客 1万+

对象的三种初始化方法

1、成员变量赋初值 public class test1 { int number = 0; int times = 0; String name = "~"; } 2、构造函数 public class test1 { int number; int times; String name; public test1() { System.out.println("执行默认构造函数"); } } public test1(int times) { System.o

FJGISer的博客 2770

DeepSeek 赋能太空探索:从轨道优化到星际开拓的 AI 革命

随着人工智能技术蓬勃发展,DeepSeek 在太空探索领域展现出巨大应用潜力。本文深入剖析 DeepSeek 技术核心,包括低功耗运算、开源生态等优势,阐述其与传统航天技术的差异。从航天器自主控制、深空探测、载人航天等关键环节,结合实时轨道调整、故障诊断修复等实例,揭示 DeepSeek 对航天任务效率与安全性的提升作用。同时探讨其应用面临的太空环境适应、伦理安全等挑战,展望技术演进方向及与前沿技术融合前景,展现 DeepSeek 为人类太空探索带来的变革与深远意义。

邓邓子的博客 2256

每天一个C++提升技巧之条款04:确定对象被使用前已被初始化

#include<iostream> #include<list> /* 本博文以及这个系列的都是我本人观看《Effective C++》的观后感,每天学习一个改善自己C++的一个小技巧。 条款04:确定对象被使用前已被初始化 在c++中读取未被初始化的值会导致不明确的行为,污染正在读取的对象,最终导致不可测的程序行为。 而处理这个问题的最佳办法是:永远在使用对象之前先将它初始化。 */ /* * 对于无任何成员的内置类型 */ int main() { int x

QQ845264718 190

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Effective C++ 01 ~ 04 条款 让自己习惯C++ 视C++为一个语言联邦 尽量以const,enum,inline替换#define 尽可能使用const 确定对象被使用前已被初始化

条款01 - 视C++为一个语言联邦 C++ 由四个次语言构成 1 . 说到底C++仍是以C为基础 区块(blocks)、语句(statements)、预处理器(preprocessor)、内置数据类型(built-in data types)、数组(arrays)、指针(pointers)都来自与C ## 2. Object-Oriented C++(面向对象) classes(包括构造函数和析构函数),封装(encapsulation)、继承(inheritance)、多态(polymorph

csxylrf的博客 189

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

指针定义时的初始化问题

一直说指针不初始化就会引发野指针问题,但是在比较指针和引用的区别的时候也说,引用定义的时候必须初始化,指针可以不用。前者的说法没有问题,后者也没有问题,具体详解如下: 首先,未初始化的指针可以称为野指针,(但是野指针并不仅仅是未初始化的指针. 一般来说,野指针指向的是内存中无效的对象),但是在定义的时候也可以不初始化,只要你在使用之前将它初始化即可,不一定是要在定义的时候,也就是说你要保证在使用的...

今天也要努力鸭 3375

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Java多线程 对象未完成初始化就把对象提供给外界--this赋值

文章目录对象未完成初始化就把对象提供给外界构造函数中未初始化完毕就this赋值 对象未完成初始化就把对象提供给外界 如下的情况, 都是对象未完成初始化就把对象提供给外界 构造函数中未初始化完毕就this赋值 如下的代码中, 演示了构造函数中未初始化完毕就this赋值 . package com.thread.background; /** * 类名称:NotInitFinishedThis * 类描述: 演示初始化未完毕,就this赋值 * * @author: https://javaweix

Java持续实践 799

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

Item 04:确定对象被使用前已先被初始化 读取未初始化的值会导致不明确的行为。而最佳的处理办法就是:永远在使用对象之前先将它初始化。

onlyshi的专栏 1479

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

Effective C++条款04条款04:确定对象被使用前已先被初始化类构造函数的初始化和赋值区别non-local static对象讨论总结 条款04:确定对象被使用前已先被初始化 永远在使用对象之前先将它初始化。至于内置类型之外的任何其他东西,确保每一个构造函数都将对象的每一个成员初始化。 类构造函数的初始化和赋值区别 #include<iostream> #include<string> using namespace std; class ABEntry { public

weixin_38688399的博客 286

C++守则——确定对象被使用前已经被初始化

C++对于初始化这件事是喜怒无常的,比方这行代码: int x; 又时候C++编译器会将它初始化为0,但有时候却又不一定。如果编译器真的读取到一个为初始化的值时就会导致各种不明确也的伪白兔,情节较轻的话就会终止程序,情节较重的话,就会读取一些伴随及的值,污染了正在进行读取动作的那个对象,最终导致不可测知的程序行为。 事实上关于对象的初始化动作合是一定发生,何时不一定发生是由一些规则的,但是这些规...

qq_43419761的博客 1213

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

一. 永远在使用对象之前将它初始化 1.对于内置类型,手动完成初始化。 例如:int =0; 2.除了内置类型之外的类型,由构造函数进行初始化:确保每个构造函数都将对象的每一个成员进行了初始化。 二. 特别区分“赋值”和“初始化” 例如:有一个类:A中有一个成员变量string name; 有一个构造函数:A(const string &n){name=n;}//这...

auo1202的博客 167

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

参考这句C++: , 在某些语境下, x 是会被初始化为 0 的, 但是某些语境下并不能保证: 有的时候, t 会将内部的 x 和 y 进行初始化, 有的时候又不会.读取没有初始化的变量会导致一些奇怪的行为, 这些行为是未被定义的. 比如指针没有初始化, 他或许不会初始化为 , 当你去访问这个地址时, 可能就导致了未知的错误和让人非常不愉快的调试出现. 现在我们有了一个规则: 读取未被初始化的变量, 结果是未知的.这是一个无法决定的事情, 相当于程序员把自己编写的程序的命运交给编译器. 其实有一个非常好

roseisbule的博客 320

EffectiveC++详解:条款04-确定对象被使用前已被初始化

文章目录条款04-确定对象被使用前已被初始化1. 切勿混淆赋值和初始化2. 内置类型的赋值操作移到函数里,以避免重复的工作3. 成员初始化次序3.1 类的成员初始化次序3.2 不同编译单元内的 `non-local static` 对象的初始化次序4. 总结 @Author:CSU张扬 @Email:csuzhangyang@gmail.com or csuzhangyang@qq.com @...

神奇小海螺的博客 4199

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

关于将“对象初始化”这事,似乎很多人觉得没什么值得注意的地方。int x;在某些语境下x保证被初始化为0,但在其他语境中却不能得到保证。在这里,p的成员变量有时候会被初始化为0,有时候不会。读取未初始化的值会导致不明确行为。在某些平台,仅仅市读取未初始化的值,就可能让你的程序终止。而最好的处理办法是:永远在使用对象之前先将它初始化。对于无任何成员的内置类型,必须手动完成这件事。对于内置类型以外的其它成员变量,初始化责任落在构造函数身上。规则很简单:确保每一个构造函数都将对象的每一个成员初始化。

依然爱猪的博客 689

《Effective C++》条款4:确定对象被使用前已被初始化

为内置型对象进行手工初始化,因为c++不保证会初始化他们构造函数使用初始化列表来初始化成员变量,而不要在构造函数内对他们另外赋值。初始化列表中变量的出现顺序尽量和他们的声明顺序相同为免除“跨编译单元的初始化次序”问题,使用的方式以对象替换对象。

2301_80345648的博客 1094

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

#条款04:确定对象在使用前已被初始化 如有问题,欢迎交流指正 永远在使用对象之前先将它初始化,特别是内置类型。 构造函数的初始化任务使用member initialization listmember\,initialization\, listmemberinitializationlist替换函数体中的赋值动作。 C++规定,对象的成员变量的初始化动作发生在进入构造函数函数体之前。 规定总是在初值列中给出所有成员变量,以免还得记住哪些成员变量无需初值。 如果类中存在多个构造函数,为避免初值列中

Wendell_0的博客 189
上一篇: 关于CString
下一篇: 利用C++模板技术支持多种计算策略
undefined_behavior
博客等级 码龄19年 1粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值