文章目录
拷贝构造函数的使用拷贝构造对于自定义类型【浅拷贝】深拷贝拷贝构造函数典型调用场景
拷贝构造函数的使用
在前几章学习对象的时候,我们有的时候需要一个与已存在对象一某一样的新对象
那在创建对象时,可否创建一个与已存在对象一某一样的新对象呢?
拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。
拷贝构造函数也是特殊的成员函数,其特征如下:
拷贝构造函数是构造函数的一个重载形式。拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。class Date{public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}//Date(const Date d) // 错误写法:编译报错,会引发无穷递归Date(const Date& d) // 必须传引用{_year = d._year;_month = d._month;_day = d._day;}private:int _year;int _month;int _day;};int main(){Date d1(2024,2,1);Date d2(d1);return 0;}
const
可加可不加,但是建议加上有些人就写这个写昏头了,写反了,不加const的话不会提示 class Date{public:// 构造函数Date(int year = 2024, int month = 2, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}private:int _year;int _month;int _day;};int main(){Date d1(2024, 2, 1);Date d2(d1);d1.Print();d2.Print();return 0;}
拷贝构造对于自定义类型【浅拷贝】
那么对于自定义类型呢?class Time{public:Time(const Time& t){_hour = t._hour;_minute = t._minute;_second = t._second;cout << "Time::Time(const Time&)" << endl;}private:int _hour;int _minute;int _second;};class Date{public:Date(int year = 2024, int month = 2, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}private:int _year;int _month;int _day;// 自定义类型Time _t;};int main(){Date d1(2024,2,1);Date d2(d1);d1.Print();d2.Print();return 0;}
我们有一个方法就是强制让编译器生成
加上这一条:
Time() = default;
深拷贝
刚刚上面的一种场景叫做浅拷贝,还有一个场景就是深拷贝
编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,还需要自己显式实现吗?当然像日期类这样的类是没必要的。那么下面的类呢?验证一下试试?
下面我这个代码没有写拷贝构造,它会自动生成一个默认的值拷贝,我们来运行一下
typedef int DataType;class Stack{public:Stack(size_t capacity = 10){_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申请空间失败");return;}_size = 0;_capacity = capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}private:DataType* _array;size_t _size;size_t _capacity;};int main(){Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2(s1);return 0;}
我们看到程序崩溃了~~ 也就是在一些场景下,默认生成的拷贝构造是会出事的
再调试看一下:
Stack(const Stack& s){// 深拷贝DataType* tmp = (DataType*)malloc(s._capacity * sizeof(DataType));if (nullptr == tmp){perror("malloc fail\n");exit(-1);}memcpy(tmp, s._array, sizeof(DataType) * s._size);_array = tmp;// 浅拷贝_size = s._size;_capacity = s._capacity;}
注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数是一定要写的,否则就是浅拷贝
拷贝构造函数典型调用场景
使用已存在对象创建新对象函数参数类型为类类型对象函数返回值类型为类类型对象class Date{public:Date(int year, int minute, int day){cout << "Date(int,int,int):" << this << endl;}Date(const Date& d){cout << "Date(const Date& d):" << this << endl;}~Date(){cout << "~Date():" << this << endl;}private:int _year;int _month;int _day;};Date Test(Date d){Date temp(d);return temp;}int main(){Date d1(2022, 1, 13);Test(d1);return 0;}
最后本文就到这里结束了,感谢大家的收看,请多多指点~