拷贝构造,是一种特殊的构造函数,它在不人为声明定义情况下默认存在于类中,它的调用出现在下面这种情况之中:
就是说,像f(Howmany x)
函数这种默认参数列表中含有类声明的情况中,在f()函数的内部实际上已经产生了基于Howmany类的对象x,也调用了默认的拷贝构造函数。另外的一种情况是:Person A;
Person B(A); //或者Person B = A;,值得注意的是,这两种定义形式在C++中是完全一样的。
这里,默认的拷贝构造函数形式如下:
也即:T::T(const T&)
,一般自己不在类中写明,系统会默认调用,但不会修改任何东西,此构造函数完成的工作仅仅是成员(member)级拷贝,就是把原来类中存在的成员变量,用到的其他对象等等全部拷贝过去(但这里不是字节级别的拷贝)。
所以, 希望在发生拷贝构造的情形下有所动作的,应当自己按照如上形式在类中定义拷贝构造函数,其他形式则不行。
进一步地
拷贝构造在成员级上的拷贝,会导致指针也发生同等指向的的问题,一般创建两个独立的对象是发生下图右面的指针各自指向情况,而不是左图的同一指向。
出现这种情况的代码如下,这样的话,编译器会报错,因为在创建两个对象之后,出现两次析构阶段,这两次析构都是释放同一内存地址,所以出现重复释放内存错误。
解决由char 带来的如上问题,可以通过如下途径:
就是自己定义一个拷贝构造函数来实现分别创建不同内存地址的成员变量初始化给另一个对象。上面这种情况,根源上讲还是因为使用了标准C的函数库中的char 这类字节级别的数据类型指针,所以为了在C++中更好的处理字符串这类数据,一般来讲最好使用C++新增的String类型来代替char *,因为String本身作为一个类,自己拥有自己的拷贝构造函数,可以将同类对象之间的拷贝构造处理得很好。
这里有两条建议:(1)自己写一个类,上来就先把三种构造函数写好:默认构造、virtual 构造、拷贝构造,先不管用不用得到。(2)初学最好不要把拷贝构造private掉,会发现用不了了。