对象在使用之前的初始化

C++规定对象的初始化动作发生在进入构造函数主体之前。(初始化列表比在构造函数体内初始化的效率高,以为在函数体内初始化会调用默认的构造函数)

编译单元是指产出单一目标文件的那些源码。

问题:

两个源码文件,每个文件中至少有一个non-local static对象(即该对象是全局的或者位于namespace作用域内,或在class内或file的作用域内被声明为static)。如果某编译单元内的non-local static对象的初始化用动作使用了另一个单元内的某个non-local static对象,在这个时候由于c++对定义在不同的编译单元内的non-local static对象的初始化次序没有明确的规定,所以用可能引发错误。

例子:

你写的程序(一个编译单元):

class FileSystem
{
 public:
     …
     size-tnumDisk() const;
     …
};
Extern FileSystem tfs;//
准备给别人用的对象

别人的程序(另一个编译单元)

class Directory
{
  Directory(params)
{
   Size_tdisk=tfs.numDisks();   //使用第一个编译单元的对象,假设在编译这个文件之//前已经编译了上一个文件那么没错,如果相反呢?
}
};

解决办法:

将每个non-local static对象搬到自己专属的函数内(也就是在函数内声明为static)。这些函数返回一个引用指向它所含的对象。在调用的时候调用这些函数而不是直接调用对象。理由(c++保证,函数内的local static对象会在该函数调用期间首次遇上该对象的定义式时被初始化)

程序修改之后:

class FileSystem
{
 public:
     …
     size-tnumDisk() const;
     …
};
FileSystem& tfs()
{  static FileSystem fs;
   returnfs;
}
 
 
Class Directory
{
  Directory(params)
{
       Size_tdisk=tfs().numDisks();   //调用函数tfs()
}
};
Directory& tempDir()
{
Static Directory td;
return td;
}

任何一种non-conststatic对象不论他是local还是non-local,在多线程的环境下等待某事发生都会有麻烦,处理麻烦的做法是:在程序单线程启动的阶段手工调用引用返回的函数,这可以消除与初始化有关的竞速形式。

总结:

一、对内置类型进行手工初始化(c++不保证初始化他们)。

二、构造函数最好使用成员初始列,而不要在构造函数内使用赋值操作,初始列的次序应该和class中的声明次序相同。

三、为免除跨编译单元的初始化问题,应该用local static对象替换non-local static对象。

时间: 2024-08-01 10:44:31

对象在使用之前的初始化的相关文章

读书笔记 effective c++ Item4 确保对象被使用前进行初始化

Item4 确保对象被使用前进行初始化 C++在对象的初始化上是变化无常的,例如看下面的例子: Int x; 在一些上下文中,x保证会被初始化成0,在其他一些情况下却不能够保证.看下面的例子: Class Point { Int x,y; }; Point p; P的数据成员有时候保证能够被初始化(成0),有时候却不能.如果你从不存在未初始化对象的语言中转到c++, 就需要注意了,因为这很重要. 使用未初始化对象的坏处 读取未初始化的值会产生未定义的行为.在一些平台中,仅仅读取未初始化的值就会让

条款47: 确保非局部静态对象在使用前被初始化

class FileSystem { ... }; // 这个类在你 // 的程序库中 FileSystem theFileSystem; // 程序库用户 // 和这个对象交互 ////////////////////////////////////////////////////////// class Directory { // 由程序库的用户创建 public: Directory(); ... }; Directory::Directory() { 通过调用theFileSystem

Objective-C对象的申请空间与初始化

对象分配空间与初始化 对象分配空间与初始化 使用Objective-C语言创建一个对象有两个步骤,你必须: 为新对象动态分配内存空间 初始化新分配的内存,并赋初值 不经过如上两步,一个对象就没有完全功能化.每个步骤都可以分步完成,不过一般的都是在用写在同一行的代码实现: Objective-c代码   id anObject = [[Rectangle alloc] init]; 把分配空间和初始化分离,你就可以分开的操作这两步,那么对其的修改也是隔离的.下文将首先关注分配内存空间,而后是初始化

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

目录 1. 总结 2. 构造函数体 VS 初始化列表 3. 对象的初始化顺序问题 1. 总结 无论是在初始化列表中,还是在构造函数体内,请为内置类型对象进行手工初始化,因为C++不保证初始化它们 最好使用初始化列表进行初始化,而不要在构造函数体中使用赋值:初始化列表最好列出所有的成员变量,其排列顺序应该和它们在class中的声明顺序相同 为了避免"不同源文件内定义的non-local static对象在编译时的初始化顺序"问题,请以local static对象替换non-local s

利用Java反射实现JavaBean对象相同属性复制并初始化目标对象为空的属性的BeanUtils

有时遇到将数据传输对象转换成JSON串会将属性值为空的属性去掉,利用Java反射实现JavaBean对象数据传输对象的相同属性复制并初始化数据传输对象属性为空的属性,然后转换成JSON串 package com.banksteel.util; import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.Arrays;import java.ut

类和对象的简单使用(构造函数初始化)

///简单的使用类和对象 #include <iostream> using namespace std; ///构造函数的重载,求体积 class Box { public: Box(); ///不带参数的构造函数,来初始化 Box(int h,int w,int l):height(h),width(w),length(l) {}; ///利用参数列表初始化 int volume(); ///求体积 private: int height; int width; int length; }

在另一个类中做数据成员的对象,可以先不初始化

class A { B b; } 因为在创建A类的时候,会先调用A的构造函数,同时对B类中的b对象调用他的构造函数 下面测试代码 class A { public: int a; A(int x) :a(x){}; }; class B:public A { private: A b; public: B(int x, int y) :A(x), b(y){} void display() { cout << a << endl << b.a << endl

[Think In Java]基础拾遗1 - 对象初始化、垃圾回收器、继承、组合、代理、接口、抽象类

目录 第一章 对象导论第二章 一切都是对象第三章 操作符第四章 控制执行流程第五章 初始化与清理第六章 访问权限控制第七章 复用类第九章 接口 第一章 对象导论 1. 对象的数据位于何处? 有两种方式在内存中存放对象: (1)为了追求最大的执行速度,对象的存储空间和生命周期可以在编写程序时确定,这可以通过将对象置于堆栈或者静态存储区域内来实现.这种方式牺牲了灵活性. (2)在被称为堆的内存池中动态地创建对象.在这种方式,知道运行时才知道对象需要多少对象,它们的生命周期如何,以及它们的具体类型.

【解惑】类与对象的初始化问题

★ 类常量 Java类常量(final修饰) 的值在编译阶段就已经写入了class文件的常量池中(可见<Class文件内容及常量池 >).该类在JVM中运行的任何阶段都不可能改变这个常量值.这也就形成了Java常量定义的两个语法规定:(1) Java类常量必须在类中声明的时候就赋给特定的值.(2) Java类常量绝对不允许赋第二次值. 下面是Java类常量的初始化代码: Java代码 //代码1: 类常量的初始化 public class Init{ //定义类常量ITEM,声明的同时必须赋值