拷贝构造函数

拷贝构造函数

一,定义:
拷贝构造函数:在定义语句中用 同类型的对象初始化另一个对象。
二,格式
用类类型本身作形式参数。
该参数传递方式为按引用传递,避免在函数调用过程中生成形参副本。该形参声明为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. 含指针成员的类通常应重写以下内容:
• 构造函数(及拷贝构造函数)中分配内存,深复制策略
• = 操作重写,完成对象深复制策略
• 析构函数中释放内存
浅拷贝 只复制成员指针的值,而不复制指向的对象实体,导致新旧对象成员指针指向 同一块内存。但深拷贝要求成员指针指向的对象也要复制,新对象跟原对象的成员指针 不会指向同一块内存, 修改新对象不会改到原对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值