对象的初始化,拷贝和析构

每个类只有一个析构函数,但可以由多个构造函数。

对于一个类,如果程序员不显式的声明定义上述函数,编译器自动的产生4个inline函数,

A();A(const A& );~A(); A& operator=(const A& )

1.不要在构造函数内做与初始化无关的工作,不要在析构函数内做与销毁对象无关的工作。

注意初始化和赋值的区别

初始化:在对象创建的同时使用初值直接填充对象的内存单元。因此不会产生类型转换等中间过程,也就不存在临时对象的产生

赋值:在对象创建好后任何时候都可调用的函数,"="运算符函数,存在类型转换,也会产生临时对象。

2.构造函数的成员初始化列表

构造函数体内部初始化数据成员,实际是赋值,而不是真正意义上的初始化。

真正的初始化是使用初始化列表,该列表的初始化工作发生在函数体内的代码被执行之前。

注意:派生类的构造函数可以在初始化列表中调用父类的构造函数,进行初始化。这样效率更高。

3.对象的构造与析构的次序

任何一个对象总是最先调用最根类的子对象,然后逐层向下扩展,知道把整个对象构造起来。析构会严格按照对象构造的相反次序执行析构函数。

4.构造函数与析构函数的调用时机

静态局部对象: 如果没有提供初始值,会调用默认构造,初始化成0.提供初始值就有拷贝构造函数。

全局对象:程序进入main之前自动调用他们相应的构造函数来初始化,但是初始化顺序不确定。提供初始值则调用拷贝构造函数,否则调用默认构造函数。main结束调析构。

对象的引用:其初始化和销毁都不会调用构造函数和析构函数。

动态创建对象:new运算符创建时,自动调用匹配的构造函数。返回地址的指针是否为静态对应各自的情况。delete运算符时会自动调用析构函数。

对象赋值:调用operator=函数。

5.构造函数和赋值函数的重载

构造函数;

默认构造函数:参数为空,或者参数都有默认值,二者不能同时存在会产生二义性。

拷贝构造函数:第一个参数为本类对象的const引用,volatile引用,const volatile引用,并且没有其他的参数,或者其他参数都有默认值。

注意:如果没有显式的定义默认构造函数,却定义了带参数的构造函数,那么后者的存在就会阻止编译器生成前者。

6.拷贝构造函数的危险

编译器会自动产生一个"按成员拷贝"的方式自动生成相应的默认函数。如果类中含有指针成员或者引用,将会发生隐含错误。所以要自己去写拷贝构造函数。

注意:拷贝构造函数是在对象被创建并用一个已经存在的对象来初始化它时调用的,而赋值函数只能把一个对象赋值给一个已经存在的对象,使得那个已经存在的对象

和源对象有相同的状态。

string a("hello")

string b("world");

string c=a//拷贝构造,最好写成string c(a)

c = b;//赋值

7.偷懒的办法来处理拷贝构造函数和拷贝赋值函数

将拷贝构造函数和拷贝复制函数声明为private,并且不实现他们,防止用户调用,防止友元函数和成员函数调用。

甚至可以把所有的构造函数和赋值函数都声明为private,这样就彻底阻止了该类的实例化,或者默认构造函数声明为private,而把其他的带参构造函数声明为public:

这样就强迫用户必须使用带参的构造函数来声明和定义对象。

时间: 2024-12-28 22:02:34

对象的初始化,拷贝和析构的相关文章

[百度空间] [转] 在 Visual C++ 中控制全局对象的初始化顺序

from: http://blog.csdn.net/classfactory/archive/2004/08/07/68202.aspx 在 C++ 中,同一个翻译单位(.cpp文件)里的全局对象的初始化顺序是先定义的对象先初始化(同时也后析构),但 C++ 标准并没有规定不同翻译单位间全局对象的初始化顺序.按照这个分析,以下的代码可能工作,也可能不工作(cout 是 C++ 用于输出的全局对象,和我们自己的对象位于不同的翻译单位): class A {    A() {        cou

直接初始化&拷贝初始化&值初始化

一.变量定义&初始值 0. 变量定义的形式 //形式一 int a; //形式二 int b = 1; 1. 初始值&初始化 对象被初始化:对象在创建时获得了一个特定的值 2. 初始化&赋值 初始化变量的一种方式:用等号=来初始化变量 这种方式让人误以为初始化是赋值的一种,其实不然,初始化不是赋值 初始化:创建变量时赋予其一个初始值 赋值:把对象的当前值擦除,而以一个新值来替代 3. 列表初始化 int a = {0}; int a{0}; 4. 默认初始化 定义变量时没有指定初值

对象的初始化与清理

随着计算机革命的发展,"不安全"的编程方式已经逐渐成为了编程代价高昂的主因之一. 正确的初始化和清理过程对于程序的安全性和性能至关重要,不同的编程语言对此具有不同的处理机制.C++中利用构造器完成初始化,当对象不再被使用时调用析构函数完成销毁,程序员需要手动完成内存释放管理过程:Java也采用了构造器完成初始化,同时提供了垃圾会收器对不再使用的内存资源进行自动管理,减轻了程序员管理手动管理内存的编程负担. 1 重载 Java(和C++)中,构造器是强制重载方法名的原因之一.因为构造器常

JAVA基础之对象的初始化

本文主要记录JAVA中对象的初始化过程,包括实例变量的初始化和类变量的初始化以及 final 关键字对初始化的影响.另外,还讨论了由于继承原因,探讨了引用变量的编译时类型和运行时类型 一,实例变量的初始化 一共有三种方式对实例变量进行初始化: ①定义实例变量时指定初始值 ②非静态初始化块中对实例变量进行初始化 ③构造器中对实例变量进行初始化 当new对象 初始化时,①②要先于③执行.而①②的顺序则按照它们在源代码中定义的顺序来执行. 当实例变量使用了final关键字修饰时,如果是在定义该fina

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

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

禁止对象之间的拷贝

如何禁止对象之间的拷贝? 将构造函数和析构函数中的任意一个设置为private,如下: class A{ public: A(){}; private: ~A(){}; A(const A&a){}; A &operator=(const A&a){return a;} }; A a; 编译报错提示:Variable of type 'A' has private destructor. 我们知道,如果我们不显性的声明拷贝构造函数和重载=,那么编译器会为我们提供默认的拷贝构造函数和

不存在继承关系各类中、不存在对象引用的对象创建初始化顺序

实例3 class One   {        One(String str)      {        System.out.println(str);       }    } class Two   {       One one_1 = new One("one-1");       One one_2 = new One("one-2");       One one_3 = new One("one-3");      Two(S

该对象尚未初始化。请确保在所有其他初始化代码后面的应用程序启动代码中调用

WebAPI使用属性路由,配置config.MapHttpAttributeRoutes();后出现错误: System.InvalidOperationException: 该对象尚未初始化.请确保在所有其他初始化代码后面的应用程序启动代码中调用 HttpConfiguration.EnsureInitialized(). 在 System.Web.Http.Routing.RouteCollectionRoute.get_SubRoutes() 在 System.Web.Http.Routi

隐式类型、对象集合初始化、匿名类型

隐式类型和对象集合初始化器是在C# 3.0中引入的. 1 隐式类型 var关键字,主要还是编译器根据变量的值来推断其类型. 1.1隐式类型的局部变量 1 class Program 2 { 3 static void Main(string[] args) 4 { 5 var stringvariable="learning hard"; 6 stringvariable=2; 7 } 8 } 其实当你把鼠标放在var上面的时候,还是可以看到其类型的. 使用隐式类型时有一些限制,包括一