赞
踩
在前几章学习对象的时候,我们有的时候需要一个与已存在对象一某一样的新对象
那在创建对象时,可否创建一个与已存在对象一某一样的新对象呢?
拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用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
可加可不加,但是建议加上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; }
最后本文就到这里结束了,感谢大家的收看,请多多指点~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。