【C++修行之道】类和对象(三)拷贝构造函数
目录
一、 概念
二、特征
正确的拷贝构造函数写法:
拷贝函数的另一种写法
三、若未显式定义,编译器会生成默认的拷贝构造函数。
四、编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,还需要自己显式实现吗?
深拷贝的写法:
五、拷贝构造函数典型调用场景:
六、总结:
一、 概念
在现实生活中,可能存在一个与你一样的自己,我们称其为双胞胎。
那在创建对象时,可否创建一个与已存在对象一某一样的新对象呢?
拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。
二、特征
拷贝构造函数也是特殊的成员函数,其特征如下:
- 拷贝构造函数是构造函数的一个重载形式。
- 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
- 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。
- 编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,还需要自己显式实现吗?当然像日期类这样的类是没必要的。那么下面的类呢?验证一下试试?
- 拷贝构造函数典型调用场景:
- 使用已存在对象创建新对象
- 函数参数类型为类类型对象
- 函数返回值类型为类类型对象
class Date { public: Date(int year = 1900, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } Date(const Date& d) // 正确写法 { // this->_year = d._year; _year = d._year; _month = d._month; _day = d._day; } Date(Date& d)// 错误写法: 它不能用于从常量对象或临时对象进行拷贝构造 { _year = d._year; _month = d._month; _day = d._day; } Date(Date d)// 错误写法:编译报错,会引发无穷递归 { _year = d._year; _month = d._month; _day = d._day; } private: int _year; int _month; int _day; }; int main() { Date d1; // 拷贝构造:用同类型的对象拷贝初始化 Date d2(d1); return 0; }正确的拷贝构造函数写法:
Date(const Date& d) // 正确写法 { // this->_year = d._year; _year = d._year; _month = d._month; _day = d._day; }这是正确的拷贝构造函数写法。它接受一个对Date类型的常量引用作为参数,这意味着它可以用于从常量对象、非常量对象甚至是临时对象进行拷贝构造。由于它的灵活性,这是最常用的拷贝构造函数定义方式。
Date(Date& d) { _year = d._year; _month = d._month; _day = d._day; }- 不能接收常量对象:这个构造函数只接受非常量引用(Date&),这意味着你不能使用它来拷贝一个常量对象。如果试图这样做,编译器会报错,因为常量对象不能被非常量引用所绑定。
- 不能接收临时对象:在C++中,临时对象(也称为右值)经常出现在表达式中,例如函数返回值或者类型转换的结果。由于这个拷贝构造函数不接受右值引用或常量引用,因此它不能用于拷贝这些临时对象。
- 发生错误操作时没有报错:赋值反了
Date(Date d)// 错误写法:编译报错,会引发无穷递归 { _year = d._year; _month = d._month; _day = d._day; }这个构造函数是错误的,会引发无穷递归。原因在于,当试图用这个构造函数创建一个Date对象时,它会尝试以值传递的方式接收一个Date对象作为参数。为了构造这个参数对象d,又需要调用拷贝构造函数,这会导致无限递归调用,最终耗尽栈空间并导致程序崩溃。
class Date { public: Date(int year, int month, int day) { _year = year; _month = month; _day = day; } /*Date(Date& d) { d._year = _year; d._month = _month; d._day = _day; }*/ // Date d3(d2); //Date(const Date& d) //{ // // this->_year = d._year; // _year = d._year; // _month = d._month; // _day = d._day; //} Date(Date* d) { _year = d->_year; _month = d->_month; _day = d->_day; } void Print() { cout
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!





