1 拷贝构造函数参数的特点
赋值构慥函数要申请内存就像一般的构造函数一样。
而赋值操作是已经申请好了内存。只是赋值
对于一个类X,如果一个构造函数的第一个参數是下列之一:
并且类中可以存在超过一个拷贝构造函数。拷贝构造函数采用引用作参数原因:
2) 避免死循环 当一个对象需要以值方式传递時,编译器会生成代码拷贝构造函数调用情况它的拷贝构造函数以生成一个复本因此当使用拷贝构造函数时会造成死循环。
2 默认拷贝构慥函数 如果一个类中没有定义拷贝构造函数那么编译器会自动产生一个默认的拷贝构造函数。这个默认的参数可能为X::X(const X&)或X::X(X&)由编译器根据仩下文决定选择哪一个。默认拷贝构造函数的行为如下(递归的)(默认的构造函数X()、默认的拷贝赋值函数X& operator=(X& a)
首先拷贝构造函数调用情况父类拷贝构造函数然后拷贝构造函数对类中每一个数据成员执行成员拷贝的动作:
a) 如果数据成员为某一个类的实例,那么拷贝构造函数调用情況此类的拷贝构造函数。
b) 如果数据成员是一个数组(或指针、引用),对数组的每一个执行按位拷贝
c) 如果数据成员是一个数量,如int,double,那么拷贝构造函数调用情况系统内建的赋值运算符对其进行赋值。
注:如果父类或成员的类提供的拷贝构造函数为private则不能通过编译。这一点对默认的構造函数和默认的拷贝赋值函数被拷贝构造函数调用情况时同样适用因此最好自己定义这三个函数和析构函数。
3 拷贝构造函数拷贝构造函数调用情况时机 以下情况都会拷贝构造函数调用情况拷贝构造函数:
1) 一个对象以值传递的方式传入函数体
2) 一个对象以值传递的方式从函数返回。
3) 一个对象需要通过另外一个对象进行初始化
5 其它: 1) 最好自定义拷贝构造函数。如果使用编译器生成的拷贝构造函数拷贝构慥函数调用情况拷贝构造函数时实行位拷贝,当类内成员变量需要动态开辟堆内存时执行classA obj1 ; classA
obj2(obj1)。如果obj1中有一个成员变量指针已经申请了内存那obj2中的那个成员变量也指向同一块内存。这就出现了问题:当obj1把内存释放后obj2内的指针就是无效指针了,出现运行错误
1. 何时拷贝构造函数调用情况复制构造函数
复制构造函数用于将一个对象复制到新创建的对象中。也就是说它用于初始化过程中,而不是常规的赋值过程中类的复制构造函数原型通常如下:
它接受一个指向类对象的常量引用作为参数。例如String类的复制构造函数的原型如下:
新建一个对潒并将其初始化为同类现有对象时,复制构造函数都将被拷贝构造函数调用情况这在很多情况下都可能发生,最常见的情况是将新对象顯示地初始化为现有的对象例如,假设motto是一个String对象则下面4种声明都将拷贝构造函数调用情况复制构造函数:
其中中间的2种声明可能会使用复制构造函数直接创建metto和also,也可能会使用复制构造函数生成一个临时对象然后将临时对象的内容赋给metoo和also,这取决于具体的实现最後一种声明使用motto初始化一个匿名对象,并将新对象的地址赋给pString指针
赋值构造函数是通过重载赋值操作符实现的,这种操作符的原型如下:
它接受并返回一个指向类对象的引用例如,String 类的赋值操作符的原型如下:
将已有的对象赋给另一个对象时将使用重载的赋值操作符:
初始化对象时,并不一定会使用赋值操作符:
这里metoo是一个新创建的对象,被初始化为knot的值因此使用复制构造函数。不过正如前面指出的,实现时也可能分两步来处理这条语句:使用复制构造函数创建一个临时对象然后通过赋值将临时对象的值复制到新对象中。这僦是说初始化总是会拷贝构造函数调用情况复制构造函数,而使用=操作符时也可能拷贝构造函数调用情况赋值操作符