目录
1.引入
C语言的拷贝,直接传值,值拷贝。
class Date
{
public:
Date(int year = 1, int month = 1, 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, 4, 26);
d1.print();
Date d2(d1);//直接传值
d2.print();
return 0;
}
但是如果只是一个堆类呢(自定义类型),直接传值会发生什么?
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
void print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
class Stack
{
public:
Stack(int n = 4)
{
if (n == 0)
{
a = nullptr;
top = capacity = 0;
}
else
{
a = (int*)malloc(sizeof(int) * n);
if (a == nullptr)
{
perror("malloc fail");
exit(-1);
}
capacity = n;
top = 0;
}
}
~Stack()
{
if (a)
{
free(a);
a = NULL;
capacity = 0;
top = 0;
}
}
private:
int* a;
int capacity;
int top;
};
int main()
{
Stack s1(10);
Stack s2(s1);
return 0;
}
编译器会报错,为什么呢?
因为Stack类(自定义类型)里面有指针,将s1里面a的地址,传给了s2里面的a,即s1里面的a与s2里面的a指向的是同一块空间,在调用完s2之后,s2里面的a就被编译器自动调用的析构函数释放了,那调用完s2之后,又会去调用析构函数对s1里面的a指向的空间进行释放,相当于会对同一块空间释放两次,同时,s1里面的a在s2里面的a释放之后又变成了野指针,这当然是不行的。
C++规定自定义类型传值传参必须用拷贝构造函数去完成,
2.拷贝构造函数的定义
拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存 在的类类型对象创建新对象时由编译器自动调用。
3.特征
拷贝构造函数也是默认的成员函数,其特征如下:
1. 拷贝构造函数是构造函数的一个重载形式。
2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错, 因为会引发无穷递归调用。
3. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按,字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。
一个拷贝构造函数的案例
4.编译器自动生成拷贝构造函数
如果我们不写拷贝构造函数,编译器会自动生成,自动生成的拷贝构造函数的特点
1.内置类型,值拷贝
2.自定义类型,去调用我们自己写的它的拷贝构造函数。
注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请 时,则拷贝构造函数是一定要写的,否则就是浅拷贝。
5. 拷贝构造函数典型调用场景
1.使用已存在对象创建新对象
2.函数参数类型为类类型对象
使用已存在对象创建新对象案例,注意这里有两种写法都可以
函数参数类型为类类型对象案例,对下面的代码进行调试,你会发现有拷贝构造函数的调用。
class Date
{
public:
Date(int year=1, int month=1, int day=1)
{
this->_day = day;
this->_month = month;
this->_year = year;
}
Date(const Date& d)
{
this->_day = d._day;
this->_month = d._month;
this->_year = d._year;
}
private:
int _year;
int _month;
int _day;
};
void Test(Date d)//函数的参数为类类型
{
cout << "Test()" << endl;
}
int main()
{
Date d1(2022, 1, 13);
Test(d1);
return 0;
}