0
点赞
收藏
分享

微信扫一扫

c++构造与析构函数:初始化或清理一个对象

mafa1993 2022-03-23 阅读 93
c++

C++中使用构造函数和析构函数来进行这两项操作。这两个函数由编译器自动调用。

构造函数在创建对象时为成员属性赋值。析构函数在对象销毁时自动调用,如果对象不销毁则不调用。

这两个函数都是写在类里面。这两个函数必须存在,如果咱们不写,则编译器会自动写上,其中函数的内容为空。

默认构造函数和有参构造函数

构造函数写于类中。构造函数可以分为以下几类,即给一个对象的属性赋初值的方式有如下几类:有参和无参、普通和拷贝。

编译器自动提供的是无参构造函数。当我们没有给出其他构造函数时,编译器才会自动生成默认构造函数。一旦我们声明了其他类型的构造函数,除非我们再自己定义一个 默认构造函数,否则类将没有构造函数。

如果类内已经给各成员属性提供了初始值,则自己定义构造函数时可以不需要再给赋初始值,其构造方式可以如下所示:

在构造函数内部可以给成员属性赋初值。如果构造函数有参,则一般给属性赋的值就是传入的参数。

      构造函数没有返回值。

拷贝构造函数

拷贝构造函数是将一个已有的对象拷贝到同一个类下的一个新对象上。凡是通过拷贝另一个对象的值来给一个对象赋初值的情况,均需要调用拷贝函数拷贝后原对象不做改变,因此参数用const引用的一个对象。

调用拷贝函数的时机一般分为以下三种:

第一种情况下,就是将原对象重新复制了一份并将其赋值给新对象,这个过程需要调用拷贝函数。

第二种情况如下所示:

将一个对象作为参数输入进函数。我们知道在使用实参给形参赋值时,如果是值传递,则需要先将实参的值拷贝一份再将拷贝后的值赋给实参(也正是因为这个原因,改变形参其实是在改变那个拷贝值,而不是原值,因此改变形参不会改变实参)。在这个过程中,如果以一个对象作为参数,则也需要将该对象先拷贝一份,故用到了拷贝函数。在函数中改变那个对象,不会影响到实参对象。

同理,通过值返回的方式来返回一个对象,也是会先拷贝一个新对象出来,再返回这个拷贝出的值。故也会用到拷贝函数。

不同构造函数的调用方式

默认构造函数的调用类似于直接用类名定义一个变量,这个变量没有初值。而另外两种构造直接会为属性赋初值。注意使用默认参数时,即使没有参数也不要加(),否则会被认为是一个声明语句。

深拷贝和浅拷贝

浅拷贝:由编译器默认实现的,简单的用于赋值的拷贝操作。以=的形式完成。

深拷贝:在堆区重新申请一块空间,进行拷贝操作。

浅拷贝在使用堆区变量时带来问题。比如我们申请了一块地址为001的堆内存给A,之后将A通过浅拷贝赋值给了B,那么在释放完B之后,堆地址001中的内容就已经被清空。则我们再去释放A,堆地址001中的内容相当于被重复释放,这时就会报错。这个问题可以使用深拷贝解决。

我们使用深拷贝,重新申请一块空间,让被赋值的B指向这块新空间。这样释放A、B就不会重复释放同一块空间了。

如现在*A指向的是地址为001的堆空间。浅拷贝就是B = A。这时A、B指向的都是同一内存。深拷贝则是B = new int(*A),即将A所指向的值放到这个新的堆空间内。这样即保证了拷贝出的值是一样的,还能保证指向两个不同的空间。

如果属性是在堆区开辟的,则应自己去写一个拷贝函数,否则就会出现浅拷贝的问题。

构造函数后加冒号

冒号后是初始化语句,一般使用场合有三种:

1.对父类进行初始化:

格式:子类构造函数():父类构造函数();

其中QMainWindow是MyWindow的父类。

2.对类成员进行初始化,即使用初始化列表的构造函数

格式:构造函数( ):属性1(初始值),属性2(初始值),。。。

rectangle(int pointX, int pointY, int Width, int Length) : m_point(pointX,pointY),m_Width(Width),m_Length(Length)

{

    ......

}

其中属性的书写顺序应按照在类内的声明顺序,因为编译器将按照这种顺序进行初始化。其中函数括号内可以给设置默认参数:

对于没有在初始化列表里出现的成员属性,将会按照默认构造函数的方式隐式初始化,或者隐式地使用类内初始值。

以下形式其实是在给各属性赋值而非初始化,其中构造函数括号内的值就是要赋给属性。

构造函数()

{

      属性1 = 初始值;

      属性2 = 初始值;

}

对于内类成员属性并没有太大区别,两种方式都可以,但当赋值的成员属性是const或者引用类型时,只能使用上一种方式,因为const或者引用类型变量只能被初始化,不能被赋值。

因此,应当使用初始化列表的形式,这才是对成员属性初始化最好的方式。

3.对类内const成员和引用类型的成员进行初始化

Const类型变量和引用类型变量必须被初始化,不能被赋值。类内的Const成员不能在构造函数内部初始化,因为这其实是赋值操作。如下所示:

因此只能在变量定义时直接初始化或使用构造函数初始化列表初始化。对于引用类型的成员也一样。

析构函数

 

同时析构函数中应包含释放堆空间的代码

构造函数放在private区里

一般情况下,构造函数放在private区里将会导致无法使用该类定义对象。但是也有一些写法会去这样写,例如一种名为singleton的类:

举报

相关推荐

0 条评论