构造函数与拷贝构造函数

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

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

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

#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

    原文作者:那我就换个名字吧
    原文地址: https://blog.csdn.net/wufeifan_learner/article/details/88986949
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞