拷贝构造函数
一,定义:
拷贝构造函数:在定义语句中用同类型的对象初始化另一个对象。
二,格式
用类类型本身作形式参数。
该参数传递方式为按引用传递,避免在函数调用过程中生成形参副本。该形参声明为const,以确保在拷贝构造函数中不修改实参的值
C::C(const C& obj);
例子:
class Cstudent
{
public:
Cstudent(string string1, string string2, int t)
:name(string1),school(string2), tele(t)
{
cout <<"construct a lei" << endl;
}
~Cstudent()
{
cout << "destroy"<<endl;
}
Cstudent()
{
cout << "construct an empty lei"<<endl;
}
Cstudent(const Cstudent& t1)
{
cout << "copy" << endl;
this->name = t1.name;
this->school = t1.school;
this->tele = t1.tele;
}
string name;
string school;
int tele;
};
int main()
{
Cstudent C1("wanger", "yizhong", 2341);
Cstudent C2=Cstudent(C1);
cout << C2.name << endl;
cout << C2.school << endl;
cout << C2.tele << endl;
Cstudent C3(C1);
cout << C3.name << endl;
cout << C3.school << endl;
cout << C3.tele << endl;
Cstudent C4 = C1;
cout << C4.name << endl;
cout << C4.school << endl;
cout << C4.tele << endl;
Cstudent C5 = Cstudent(Cstudent("wanger", "yizhong", 2341));
cout << C5.name << endl;
cout << C5.school << endl;
cout << C5.tele << endl;
return 0;
}

1.调用Cstudent的拷贝构造函数用对象obja初始化对象objb。如果有为Cstudent类明确定义拷贝构造函数,将调用这个拷贝构造函数,并且编译器不会再生成默认拷贝函数;如果没有为Cstudent类定义拷贝构造函数,将调用默认拷贝构造函数。
2.
Cstudent C2=Cstudent(C1);
Cstudent C3(C1);
Cstudent C4 = C1;
--三者等价,只调用了拷贝构造函数,就完成了对象的创建与赋值。
特别地
-
Cstudent C5 = Cstudent(Cstudent("wanger", "yizhong", 2341));中的Cstudent("wanger", "yizhong", 2341)调用了有参数的构造函数,但是它没有调用析构函数,没有销毁,若该过程创建了动态内存,要手动释放。没有调用拷贝构造函数,=是指按位复制,是浅复制。
-
Cstudent C4=C1;与1.Cstudent C4;C4=Ctudent(C1)和2.Cstudent C4;C4=C1不等价
1.C4=Ctudent(C1)先调用了拷贝构造函数,再调用了=操作符
2.C4=C1只调用了=操作符
3.销毁顺序:C5,C4,C3,C2,C1
三,拷贝构造函数的触发
1.声明 C x(c) 或 new C(c) 会触发复制构造
2.将一个对象作为实参,以按值调用方式传递给被调函数的形参对象。假定C为已定义的类,obja为C类对象,且
void fun(C temp)
{ …
}
fun(obja)
-
obja传递给fun函数,创建形参对象temp时,调用C的拷贝构造函数用对象obja初始化对象temp,temp生存期结束被撤销时,调用析构函数
-
若参数是C& tmp,则不会触发拷贝构造函数和析构函数,而是为obja,取别名tmp;
class Cstudent
{
public:
Cstudent(string string1, string string2, int t)
:name(string1),school(string2), tele(t)
{
cout <<"construct a lei" << endl;
}
~Cstudent()
{
cout << "destroy"<<endl;
}
Cstudent()
{
cout << "construct an empty lei"<<endl;
name = "\0";
school = "\0";
tele = 0;
}
Cstudent(const Cstudent& t1)
{
cout << "copy" << endl;
this->name = t1.name;
this->school = t1.school;
this->tele = t1.tele;
}
string name;
string school;
int tele;
void print(Cstudent& another)
{
cout << another.name<<endl;
another.name="zhangjiaxin";
}
};
int main()
{
Cstudent C1("wanger", "yizhong", 2341);
Cstudent C2=Cstudent(C1);
C1.print(C2);
return 0;
}
输出:

3.(旧版)生成一个临时对象作为函数的返回结果:当函数返回一对象时,系统将自动创建一个临时对象来保存函数的返回值。创建此临时对象时调用拷贝构造函数,当函数调用表达式结束后,撤销该临时对象时,调用析构函数。
(新版优化)但现在的gcc/g++不这么处理,会做一个优化。在Cstudent函数里有个c变量,离开func时不撤销这个对象,而是让new C和这个对象关联起来(但是不需要手动释放return c中c的内存)。也就是说tmp的地址和new C是一样的。
class Cstudent
{
public:
Cstudent(string string1, string string2, int t)
:name(string1),school(string2), tele(t)
{
cout <<"construct a lei" << endl;
}
~Cstudent()
{
cout << "destroy"<<endl;
}
Cstudent()
{
cout << "construct an empty lei"<<endl;
name = "\0";
school = "\0";
tele = 0;
}
Cstudent(const Cstudent& t1)
{
cout << "copy" << endl;
this->name = t1.name;
this->school = t1.school;
this->tele = t1.tele;
}
string name;
string school;
int tele;
Cstudent setup()
{
Cstudent c("zhangjiaxin", "sysu", 19);
//只调用了构造函数
//如果传c的地址,并用Cstudent* c1接收,则起不到复制效果,c1指向的空间为空。
Cstudent a("zhangjiaxin", "sysu", 29);//调用了析构函数和构造函数
return c;//a在这里调用析构函数,c不调用析构函数
}
};
int main()
{
Cstudent C1("wanger", "yizhong", 2341);
Cstudent C2=Cstudent(C1);
Cstudent c = C1.setup();//Cstudent c没有调用构造函数和拷贝构造函数,代码中的=是按位复制,依旧是浅复制;Cstudent c1( C1.setup());Cstudent c没有调用拷贝构造函数,代码中的=是按位复制,只进行了浅复制。
cout << c1.name << endl;
return 0;
}

四,拷贝构造函数自定义
1. 对于不含指针成员的类,使用系统提供(编译器合成)的默认拷贝构造函数即可。
2. 缺省(默认)拷贝构造函数使用浅复制策略,不能满足对含指针数据成员的类需要。
3. 含指针成员的类通常应重写以下内容:
• 构造函数(及拷贝构造函数)中分配内存,深复制策略
• = 操作重写,完成对象深复制策略
• 析构函数中释放内存
浅拷贝只复制成员指针的值,而不复制指向的对象实体,导致新旧对象成员指针指向同一块内存。但深拷贝要求成员指针指向的对象也要复制,新对象跟原对象的成员指针不会指向同一块内存,修改新对象不会改到原对象。
2682

被折叠的 条评论
为什么被折叠?



