构造函数与拷贝构造函数

拷贝构造函数和构造函数不能分开说,他们都是初始化对象的一种方法。但是我们这里用构造函数辅助说明拷贝构造函数,主要说说拷贝构造函数的声明,用途和使用注意事项。


众所周知,构造函数是一个初始化类对象的函数,即使不显示调用,编译器也会隐式调用构造函数初始化类对象。同样的,拷贝构造函数是一种特殊的构造函数,目的也是初始化类对象,同样在不声明的情况下也会隐式调用该函数。而隐式调用拷贝构造函数的时候,我们称之为“浅拷贝”。但是,请注意一点,并不是说显示调用就是“深拷贝”,而是如果要深拷贝一定要显示调用

深浅拷贝后文会说,现在我们着重考虑其用途:

#include <iostream>
using namespace std;
class A{
private:
    int a;
public:
    A(int b):a(b){
        cout<<"构造函数"<<endl;
    }
    A(const A& c){
        a = c.a;
        cout<<"拷贝构造函数"<<endl;
    }
    ~A(){
        cout<<"析构函数"<<endl;
    }
};
int main(){
    A a(100);   //调用构造函数
    A b = a;    //调用拷贝构造函数
    return 0;
}

看图,当创建了一个对象a时,编译器调用构造函数将a初始化为100。当又创建了一个对象b,将a赋值于b,此时调用拷贝构造函数将b初始化。最后由于调用了一次构造函数一次拷贝构造函数,所以析构函数被调用两次。

那么将主函数部分稍作修改,改成:

int main(){
    A a(100);
    A b(200);
    b = a;
    return 0;
}

会怎样呢?

可见,当我们对函数初始化完成,就不会再调用拷贝构造函数了,这时候b=a就是简单的赋值运算操作,和拷贝构造无关。


程序稍作改动,当类对象以参数的形式存在在普通函数中,会怎么样?

#include <iostream>
using namespace std;
class A{
private:
    int a;
public:
    A(int b):a(b){
        cout<<"构造函数"<<endl;
    }
    A(const A& c){
        a = c.a;
        cout<<"拷贝构造函数"<<endl;
    }
    ~A(){
        cout<<"析构函数"<<endl;
    }
    void newA(A b){
        cout<<"bbbbb"<<endl;
    }
};
int main(){
    A a(100);
    a.newA(a);
    return 0;
}

理论上来说,调用函数newA(a)会利用构造函数构造一个新的b对象,实际上呢?

我们看到,它调用的是拷贝构造函数。为什么?

不知道,我们就改动一下程序,直接查看b对象中a的值:

void newA(A b){
        cout<<b.a<<endl;
    }

奇怪了,我们明明没有对b初始化,它却生成了b=100。是这样么?当然不是。

我们传的参数是a,而a已经被初始化为100。这时候形参是 A b = a 的。是不是看出点东西了。

所以,在调用void newA(A b){}的时候,实际上是创造了一个形参,这个形参被拷贝构造函数初始化为已经被构造函数初始化的a初始化。说的别扭,就上图。


总结一下,什么时候调用拷贝构造函数?就是当使用“=”赋值的时候,需要用到拷贝构造函数。

关于深浅拷贝,请看:深拷贝与浅拷贝

 

参考资料:https://www.cnblogs.com/alantu2018/p/8459250.html

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值