1.拷贝构造是构造函数的重载
2.拷贝构造函数的第一个第一个参数必须是类类型(自定义类型)的引用,使用传值方式编译器直接报错,因为语法逻辑会引发无穷递归调用,拷贝构造函数也可以多个参数,但是第一个参数必须是类类型对象的引用,后边参数必须有缺省值
3.C++规定自定义类型对象进行拷贝行为必须调用拷贝构造,所以这里自定义类型传值传参和传返回值都会调用拷贝构造完成
4.若未显式定义拷贝构造,编译器会自动生成拷贝构造函数,自动生成拷贝构造对内置类型成员变量会完成值拷贝/浅拷贝(日期类Date)(一个字节一个字节的拷贝),对自定义类型的成员变量会调用它的拷贝构造,但是对于Stack必须完成深拷贝,因为Stack中int*_a这个变量会指向另外一块空间,完成值拷贝只能拷贝它的值,不能拷贝它所指向的那块空间(所以我们拷贝栈的时候不能只拷贝它的值,更要拷贝它开辟的空间)
#include<iostream>
class Date
{
public: Date(int year=1, int month=1, int day=1) {
_year = year;
_month = month;
_day = day;
}
//拷贝构造函数,权限缩小
Date( const Date & d) {
_year = d._year;
_month = d._month;
_day = d._day;
}
//析构函数
~Date()
{
std::cout << "Date的析构函数被调用" << std::endl;
}
private: int _year;
int _month;
int _day;
};
int main()
{
Date d1(2025,10,28);
Date d2(d1);//用d1拷贝给d2
Date d2 = d1;//也是拷贝构造
return 0;
}
日期类就算不写拷贝构造,系统也会自动生成拷贝构造
Stack类
class Stack {
public:
//构造函数
Stack(int n=4) {
_a = (int*)malloc(sizeof(int) * n);
if (_a == nullptr) {
perror("malloc fail!");
exit(1);
}
_capacity = n;
_top = 0;
}
//拷贝构造,深拷贝
Stack(const Stack&st) {
_a = (int*)malloc(sizeof(int) * st._capacity);
if (_a == nullptr) {
perror("malloc fail!");
exit(1);
}
memcpy(_a,st._a,sizeof(int)*st._top);
_top = st._top;
_capacity = st._capacity;
}
private:
int* _a;
int _capacity ;
int _top ;
};
int main()
{
Stack st1;
Stack st2(st1);
return 0;
}
此处运行出来指向的不是同一块空间
内置类型Date类(int,double......)会默认生成拷贝构造,自定义类型会调用自己的拷贝构造,Stack要自己实现深拷贝(因为_a额外申请了一块资源),但是MyQueue除外,会调用Stack的拷贝构造
6.小技巧:如果一个类显示写了析构函数(Stack)并释放资源,那么他就需要显示写拷贝构造,否则就不需要。
///7.注意以下这个代码:不是所有的拷贝构造都能用传引用返回(局部对象不能用传引用返回)
因为此处Func()中这个对象出了作用域之后就销毁了,所以不能用引用返回,但是如果加上个static就能用引用返回,因为出了作用域之后不会被销毁
Stack& Func()
{
Stack st;
st.push(1);
st.push(2);
st.push(3);
return st;
}
int main() {
Stack ret = Func();
cout << ret.Top() << endl;
return 0;
}
以下代码正确
Stack& Func()
{
static Stack st;
st.push(1);
st.push(2);
st.push(3);
}
int main() {
Stack ret = Func();
cout << ret.Top() << endl;
return 0;
}