目录
定义:
同一个类的对象在内存中有完全相同的结构,如果作为一个整体进行复制或称拷贝是完全可行的。这个拷贝过程只需要拷贝数据成员,而函数成员是共用的(只有一份拷贝)。在建立对象时可用同一类的另一个对象来初始化该对象的存储空间,这时所用的构造函数成为拷贝函数。
#include<iostream>
class Complex
{
private:
int real;
int image;
public:
Complex():real(0),image(0){}
Complex(int r,int i):real(r),image(i){}
Complex(const Complex &com) //拷贝构造函数,不能对被拷贝的值进行修改因此加上const修饰,形参
//使用引用,不能使用值传递,造成无穷递归
{
real=com.real;
image=com.image;
}
//拷贝构造函数属于构造函数的一种重载,因此可以采用初始化列表
Complex(const Complex &com):real(com.real),image(com.image) //先构造real和Image再进入构造
//函数体内部
{
cout<<"Copy Create Complex(const Complex &)"<<endl;
}//按位拷贝
};
void fun(Complex cs) //使用值传递,拷贝构造形参
{
}
int main()
{
Complex ca;
Complex cb(1,2);
Complex cc(cb); //拷贝构造
return 0;
}
总结:
拷贝构造函数的参数--采用引用。如果把一个真实的类对象作为参数传递到拷贝构造函数,会引起无穷递归。
在类中如果没有显式给出拷贝构造函数时,则c++编译器自动给出一个缺省的拷贝构造函数。如果有程序设计者定义的构造函数(包括拷贝构造函数),则按函数重载的规律,调用合适的构造函数。
缺省的拷贝构造函数的特点:按位拷贝。
浅拷贝:
class CGoods
{
private:
enum {LEN=20};
char Name[LEN];
int Amount;
float Price;
float Total_value;
public:
CGoods():Name{},Amount{},Price{},Total_value{}
{
//memset(this,0,sizeof(CGoods)); 不得在构造函数中使用mem,由于虚表和虚函数特性
}
CGoods(const char* name,int amount,float price)
{
strcpy_s(Name,LEN,name);//字符串的赋值必须采用strcpy
Amount=amount;
Price=price;
Total_value=amount*price;
}
CGoods(const Cgoods &c)
{
//memcpy(this,&c,sizzeof(CGoods)); 也会将虚表修改掉,不可以这样写
//Name=c.Name; 这样也是错误的,必须使用strcpy_s拷贝
strcpy_s(Name,LEN,c.Name);
Amount=c.Amount;
Price=c.Price;
Total_value=c.Total_value;
cout<<"Copy CGoods(const Cgoods &)"<<endl;
}
};
int main()
{
CGoods book("C++",10,128.0);
CGoods bx(book);
return 0;
}
类类型作为函数的形参:
1. 值传递 2.引用传递 3.常引用传递
void funa(CDate dt) //首先构造dt,再传入da1对dt进行初始化构造,将值传入
{
}
void funb(CDate & dt) //直接以引用传入,会修改到实参的值
{
}
void func(const CDate&dt) //只引用值,不修改
{
}
int main()
{
CDate da1(2022,6,8);
CDate da2(da1);
funa(da1);
return 0;
}
类类型作为函数返回值:
1.函数的返回只能以类的值返回,不能以引用返回。
2.如果函数的返回值不受函数生存期的影响,就可以以引用返回。
CDate get_CDate_1() //以值返回的话,返回值给主函数时会构造一个临时对象(将亡值)
{
CDate dt(2025,4,5);
return dt;
}
CDate get_CDate_2()
{
return CDate(2025,4,9); //直接在main中构造临时对象并返回
}
CDate & get_CDate_3() //不能用引用返回,在函数调用后函数的栈空间被回收。如果对象生存期不受函数
//影响,可以采用左值引用返回
{
CDate dt(2025,4,5);
return dt;
}
CDate& get_CDate_4()
{
return CDate(2025,4,9); //临时对象在c11中属于右值,不能以左值引用返回
}
CDate&& get_CDate_5()
{
return CDate(2025,4,9); //构造完临时对象后,立马析构掉临时对象,如果以引用返回,将返回失败
}
int main()
{
CDate dta;
dta=get_CDate_1(); //临时对象将值赋给dta,后析构掉自身
dta.ShowDate();
return 0;
}