第13章复制控制
【89】13.1什么是复制构造函数?何时使用它?
答:复制构造函数是具有如下特点的构造函数:只有单个形参,且形参是对本类类型对象的引用(常用const修饰)
复制构造函数在下列情况下使用:
根据另一个同类型的对象显式或隐式初始化一个对象。
复制一个对象,将它作为实参传给一个函数。
从函数返回时复制一个对象。
初始化顺序容器中的元素。
根据元素初始化式列表初始化数组元素。
【90】13.2下面的第二个初始化不能编译。可以从vector的定义中得出什么推断?
vector<int> v1(42);
vector<int>v2=42; //error!
答:vector容器类没有提供公有的复制构造函数。因为第二个初始化是复制初始化,创建v2时,编译器首先调用接受一个int型形参的vector构造函数,创建一个临时vector对象,然后,编译器需要使用vector复制构造函数将v2初始化为该临时vector对象的副本。
【91】13.5哪个类定义可能需要一个复制构造函数?
a)包含4个float成员的Point3w类
不需要,因为该类中的数据成员都是内置类型的,没有指针成员,使用编译器提供的复制构造函数即可;
b)Matrix类,其中,实际矩阵在构造函数中动态分配,在析构函数中删除;
需要,因为需要涉及指针及内存的动态分配;
c)PayRoll类,在这个类中为每个对象提供唯一ID。
需要,因为在根据已存在的PayRoll对象创建其副本时,需要提供唯一的ID;
d)Word类,包含一个string和一个以行列位置对为元素的vector。
不需要,因为编译器会自动为其数据成员调用string和vector的复制构造函数;
答:一般而言,如果一个类拥有指针成员,或者存在复制对象时有一些特定工作要做,则该类需要复制构造函数。
【92】13.6复制构造函数的形参并不限制为const,但必须是一个引用。解释这个限制的基本原理,例如,解释为什么下面的定义不能工作?
Sales_item::Sales_item(const Sales_item chs);
答:上述定义之所以不能工作,是因为它试图以传值方式将实参传递给一个复制构造函数。但是,每当以传值方式传递参数时,会导致调用复制构造函数,因此,如果要使用以传值方式传递参数的复制构造函数,必须使用一个“不以传值方式传递参数“的复制构造函数,否则,就会导致复制构造函数的无穷递归调用。所以,复制构造函数的形参必须是一个引用,即以传址方式传递参数。
【93】13.7类合适需要定义赋值操作符?
答:一般而言,如果一个类需要定义复制构造函数,则该类也需要定义赋值操作符。具体而言,如果一个类中包含指针型数据成员,或者在进行赋值操作时有一些特定工作要做,则该类通常需要定义赋值操作符。
【94】13.11什么是析构函数?合成析构函数有什么用?什么时候会合成析构函数?什么时候一个类必须定义自己的析构函数?
答:析构函数是特殊的成员函数,其名字是在类名字前加上一个~。该函数没有返回值和形参,用于对象超出作用域或需要删除对象时来清除对象。
合成析构函数的作用:按对象创建时的逆序撤销每个非static成员。对于类类型的成员,合成析构函数调用该成员的析构函数来撤销对象。
编译器会为每个类合成析构函数。如果有些工作(如释放资源、执行特定操作等)需要析构函数完成,一个类就必须定义自己的析构函数。