C++(五)拷贝构造函数与调用分析

拷贝构造函数

拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它必须的一个参数是本类型的一个引用变量

拷贝构造函数,也是必要的时候才会生成,不是百分百

创建一个类

class CA

{

public:

    int m_nNumber;

}

创建两个实例

CA obj1;

obj1.m_nNumber = 10;

CA obj2;

obj2 = obj1;

int类型是基础类型,编译器认识,可以直接进行简单的成员变量初始化,原理是值赋值,不需要合成拷贝构造函数

std::cout << obj2.m_nNumber << std::endl; 结果表明obj2被拷贝了,但内部没有拷贝构造函数

再次构造一个类

class CN

{

public:
    int m_nNumber;

}

此时在CA中创建一个CN成员 CN obj;

此时

obj1.m_nNumber = 10;

obj1.obj.m_nNumber = 20; 

CA obj2 = obj1;

此时也没有拷贝构造函数

由于CN obj中成员变量仅基础类型,所以编译器也把CN作为简单类型进行值复制了

此时在CN中加一个构造函数和拷贝构造函数

拷贝构造函数的前提是由默认构造函数

CN类中创建:

CN(){};

CN(CN & obj){std::cout << "CN拷贝构造函数" << std::endl}  

运行程序,有拷贝构造函数

但此时如果没有在主函数中调用拷贝obj2 = obj1和std::cout << obj2.m_nNumber << std::endl;

运行程序,没有拷贝构造函数只有构造函数

在没有进行拷贝行为情况下,编译器清除掉了拷贝构造函数

继承

使CA继承CN

运行程序,没有调用拷贝构造函数

此时调用拷贝CA obj2 = obj1;发现有默认构造函数

当父类有拷贝构造函数,子类涉及拷贝时,父类就会调用拷贝构造,子类也会生成拷贝构造,因为在生成子类对象时,也生成了父类的子对象

虚函数

CA中加上虚函数 virtual void test(){}

有虚函数就有虚函数表,两个对象之间无法直接拷贝虚函数表,编译器生成拷贝构造函数,拷贝虚函数表

编译器对类的调用分析

拷贝构造函数应用原理

class CA

{

public:

    int m_nNumber;

    CA(){std::cout << "构造函数" << std::endl};

    CA(CA & obj){std::cout << "拷贝构造函数" << std::endl};

    ~CA(){std::cout << "析构函数" << std::endl};

}

CA obj;  调用构造函数

obj.m_nNumber = 111;

CA obj1 = obj;

CA obj2(obj);

CA obj3 = (obj);

运行程序打印,发现调用了一次构造三次拷贝构造

三个拷贝构造的过程:以CA obj1 = obj 为例

一 前半部分 是为对象obj1申请空间,同malloc 不需要调用构造函数

但如果是new新建一个对象时,会调用默认构造函数,new的内部实现是在申请内存后,再调用默认构造函数,delete同理

二 后半部分是obj.CA::CA(obj) 实际调用obj的CA作用域下的拷贝构造函数,将需要拷贝的对象当作参数传进去,相当于obj.func()调用普通函数

对象调用函数一

CA类中再次添加一个函数

void test(CA obj)

{

    return;

编译器会拷贝一个临时对象作为临时参数传入test函数,返回时析构临时对象

主函数运行:

CA* obj = new CA; 调用默认构造函数

test(*obj); 传参(注意指针,不同于引用)进入test函数,编译器拷贝了一个临时对象作为传入的参数

obj进入test函数,拷贝构造一个临时对象传参给该函数。

进入该函数,返回,临时的对象析构 ,返回main函数

delete obj;调用析构函数,析构boj对象。

运行流程:构造函数 拷贝构造函数 析构函数 析构函数

对象调用函数二

修改test函数

CA test() 函数传进编译器时是 CA test(CA &temp)因为该函数必须有一个对象返回,所以编译器创建一个临时对象

{

    CA obj; 调用第一次构造函数

    return obj; 调用temp.CA::CA(obj) 将obj拷贝到临时对象temp,返回时调用析构函数,析构obj

}

CA obj = test(); temp临时变量以赋值的方式给obj赋值而非拷贝

运行程序发现调用一次构造函数一次拷贝构造函数一次析构函数

对象调用函数三

添加一个新的函数

void CAtest()

{

    std::cout << "CAtest()" << std::endl

}

test().CAtest() 

如上个函数可知,利用test生成一个对象后并没有析构。

所以此时调用test()相当于生成了一个匿名对象,所以该语句运行结束后,匿名对象释放,调用析构函数

调用构造 拷贝构造 析构 打印CAtest() 析构

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值