【05】了解C++默默编写并调用那些函数

时间:2023-03-08 20:42:42
【05】了解C++默默编写并调用那些函数

1、如果没有声明copy构造方法,copy赋值操作符,和析构方法,编译器会自动生成这些方法,且是inline。

2、如果没有声明任何构造方法,编译器会自动生成一个default构造方法,且是inline。

3、编译器总是为我们生成一个合成析构方法。

4、首先考虑,编译器生成的copy构造方法做什么事?

  copy构造方法是一个特殊的构造方法,形参是const T&。编译器生成的copy构造方法逐个成员初始化。逐个成员初始化:对于创建对象的每个non-static字段,使用现有对象的字段去初始化。

  如果字段是类类型,递归调用类的copy构造方法。如果是内置类型,逐个bit拷贝。需要注意的是:对于引用和指针,复制引用和指针。不同类型的指针,指明了指向对象的类型,但是指针本身是int类型,就是一个地址,引用是用指针实现出来的。因此,对于引用和指针,也是逐个bit拷贝,因为它们本身的类型是int。

  还有一个特殊的情况:类中的数组。一般情况下,数组是不能赋值的,但是类中的数组是可以复制的,逐个元素进行拷贝。

  对于编译器生成的copy构造方法,可以这样认为:在初始化列表中,使用现有对象的每个字段去初始化正在创建对象的字段。

5、编译器生成的copy赋值操作符做什么事?

  copy赋值操作符,就是重载了操作符=,返回T&,形参是const T&。编译器生成的copy赋值操作符逐个成员赋值。逐个成员赋值:对于当前对象的每个non-static字段,使用rhs的字段进行赋值。那么问题来,

  我们知道,类中的有些字段是只能初始化,不能赋值的,也就是不能修改。包括:类中的引用和const字段,这种情况下,编译器不会为我们生成copy赋值操作符。

  还有一种情况,父类的copy赋值操作符是private,编译器也不会为子类生成copy赋值操作符。为什么?因为子类期望调用父类的copy赋值操作符,对父类的成分赋值,由于父类的copy赋值操作符是private,不能调用,编译器也就不为子类生成copy赋值操作符了。

6、可以认为有两个析构方法:析构方法和合成析构方法。前者用于释放动态获取的资源,后者用于按对象创建的逆序撤销每个non-static字段。对象超出作用域,先调用析构方法,再调用合成析构方法,在合成析构方法中,对于类类型,递归调用它的析构方法和合成析构方法,对于内置类型,不需要做什么。

  有个三法则:如果类需要析构方法,那么它也需要自定义copy构造方法和copy赋值操作符。为什么?怎么理解?

  析构方法,用于释放动态获取的资源,定义了析构方法,说明类中有指针。在上文中,我们知道,指针本身是int类型,copy构造和copy赋值的时候,只是拷贝指针值,并没有拷贝指向的对象,这就导致两个对象中的指针,指向同一块数据,这往往不是程序员所期望的。因此,需要自定义copy构造和copy赋值,对指向的数据也进行拷贝,也就是深拷贝。

7、编译器生成的default构造方法,成员初始化列表为空,这就意味着,类中的内置类型字段没有被初始化。为了保证对象被使用之前,先被初始化,这情况下需要提供一个构造方法,对内置类型的字段初始化。