复制构造函数会出现和赋值运算符类似的问题。
复制构造函数用于将一个对象复制到新创建的对象中。也就是说,它用于初始化过程中(包括按值传递参数)而不是常规的赋值过程中。
类的复制构造函数接收一个指向类对象的常量引用来作为参数,原型通常如下:
Class_name(const Class_name &);
-
何时调用复制构造函数
新建一个对象并将其初始化为同类现有对象时,复制构造函数都将被调用。
例如,假设motto是一个StringBad 对象,则下面4种声明都将调用复制构造函数:StringBad ditto(motto); StringBad metto = motto; StringBad also = StringBad(moto); StirngBad * pStringBad = new StringBad(motto);
具体说,当函数按值传递对象或函数返回对象时,都将使用复制构造函数。
-
默认的复制构造函数的功能
默认的复制构造函数逐个复制非静态成员(成员复制也称为浅复制),复制的是成员的值。如果成员本身就是类对象,则将使用这个类的复制构造函数来复制成员对象。静态函数不受影响,因为它们属于整个类,而不是各个对象。
-
使用复制构造函数易出现的问题
默认的复制构造函数使用的是浅拷贝,如上图中类对象motto和ditto中的成员str保存的是同一个地址。若此时motto先调用了析构函数释放掉该地址的空间,而ditto后面调用析构函数的时候成员str所指向的地址已被释放,会导致不确定的后果。为解决该问题,应采用深拷贝定义一个显式的复制构造函数,如下:
StringBad::StringBad(const StringBad &st) { num_strings++; len = st.len; str = new char[len + 1]; }
必须自定义复制构造函数的场景: 如果类中包含了使用new
初始化的指针成员,应当定义一个复制构造函数,以复制指向的数据,而不是指针。
评论区