C++ C++;复制构造器

C++ C++;复制构造器,c++,copy-constructor,copy-assignment,C++,Copy Constructor,Copy Assignment,我试图很好地掌握复制构造函数&我已经找到了这部分代码 #include<iostream> using namespace std; class A1 { int data; public: A1(int i = 10) : data(i) { cout << "I am constructing an A1 with: " << i <&l

我试图很好地掌握复制构造函数&我已经找到了这部分代码

 #include<iostream>
    using namespace std;
    class A1 {
        int data;
    public:
        A1(int i = 10) :
                data(i) {
            cout << "I am constructing an A1 with: " << i << endl;
        }
        A1(const A1& a1) :
                data(a1.data) {
            cout << "I am copy constructing an A1" << endl;
        }
        ~A1() {
            cout << "I am destroying an A1 with: " << data << endl;
        }
        void change() {
            data = data * 10;
        }
    };
    class A2 {
        int data;
    public:
        A2(int i = 20) :
                data(i) {
            cout << "I am constructing an A2 with: " << i << endl;
        }
        A2(const A2& a2) :
                data(a2.data) {
            cout << "I am copy constructing an A2" << endl;
        }
        ~A2() {
            cout << "I am destroying an A2 with: " << data << endl;
        }
        void change() {
            data = data * 20;
        }
    };
    class A3 {
    public:
        A3() {
            cout << "I am constructing an A3" << endl;
        }
        A3(const A3& a3) {
            cout << "I am copy constructing an A3" << endl;
        }
        ~A3() {
            cout << "I am destroying an A3" << endl;
        }
        void change() {
            cout << "Nothing to change" << endl;
        }
    };
    class A {
        A1 a1;
        A2 a2;
        A3 a3;
    public:
        A() {
            cout << "I am constructing an A" << endl;
        }
        A(const A& a) :
                a1(a.a1) {
            cout << "I am copy constructing an A" << endl;
        }
        ~A() {
            cout << "I am destroying an A" << endl;
        }
        A& operator=(const A& a) {
            cout << "I am performing a stupid assignment between As" << endl;
            if (this != &a)
                a1 = a.a1;
            return *this;
        }
        void change() {
            a1.change();
            a2.change();
            a3.change();
        }
    };
    class BigA {
        A data1;
        A& data2;
    public:
        BigA(A& a) :
                data1(a), data2(a) {
            cout << "I just constructed a BigA" << endl;
        }
        ~BigA() {
            cout << "I am destroying a BigA" << endl;
        }
        A get(int index) {
            if (index == 1)
                return data1;
            else
                return data2;
        }
    };
        BigA volta(BigA& biga)
     //BigA& volta(BigA& biga)
            {
        cout << "Volta ta data?" << endl;
        return biga;
    }
    int main() {
        A first;
        BigA biga(first);
        volta(biga).get(2).change();
        return 0;
    }
编辑分配运算符查询:如果我在BigA中添加此函数

void change() {
    A& rdata1 = data1;
    A cdata2 = data2;
}
并从main调用它:
biga.change()为什么不调用默认赋值运算符,而是调用复制构造函数和构造函数,我得到

I am copy constructing an A1
I am constructing an A2 with: 20
I am constructing an A3
I am copy constructing an A
编辑\u AnsweringMyOwnQuery:我刚刚发现这是由复制构造函数初始化的,而不是由赋值运算符赋值的。

让我们从它开始

A第一
创建对象时,其字段(非静态成员)将被初始化

“”

正在调用您的无参数构造函数版本:

I am constructing an A
BigA volta(BigA& biga)
{
    cout << "Volta ta data?" << endl;
    return biga;
}
当你写作时

BigA-BigA(第一)
调用了一个
BigA
构造函数。它引用
a
对象,因此不会复制
first
(在提供值时设置引用)

然后,成员初始值设定项列出时间

BigA(A& a) :
            data1(a), data2(a)
data1
的类型为
A
,复制
第一个
对象(此处引用为
A

一个新的
对象由它自己的复制构造函数创建。首先,它为
A1
调用复制构造函数

A(const A& a) :
a1(a.a1)

I am copy constructing an A1
然后,
A
a2
a3
字段默认初始化

I am constructing an A2 with: 20
I am constructing an A3 
然后执行
A1
的复制构造函数主体:

I am copy constructing an A
I just constructed a BigA
让我们回到
BigA
初始化。我们谈到了迄今为止的
data1
初始化,以及
A&data2
的时间:

BigA(A& a) :
            data1(a), data2(a)
由于它是引用,并且传递引用来初始化它,所以它只是一个赋值,没有输出

BigA
构造函数(采用
A&
)主体,然后执行:

I am copy constructing an A
I just constructed a BigA
现在,我们将试图弄清楚发生了什么

volta(biga).get(2.change()
正在调用此函数:

I am constructing an A
BigA volta(BigA& biga)
{
    cout << "Volta ta data?" << endl;
    return biga;
}
函数返回类
BigA
的未命名对象,因此应该调用复制构造函数

您没有提供像
BigA(const-BigA&BigA)
这样的复制构造函数,因此正在调用默认复制构造函数。 它对数据1执行
的顺序成员初始化然后
A&data2

通过复制未命名对象的
data1
字段初始化第一个成员,从而调用
A
的复制构造函数。上面解释了此处打印的内容(请参阅:一个新的
A
对象由其自己的复制构造函数创建…)

然后,
get
方法以
index==2运行

A get(int index) {
        if (index == 1)
            return data1;
        else
            return data2; // <--- this line is executed
最后,
change
运行

void change() {
        a1.change();
        a2.change();
        a3.change();
    }
只有
a3.change()
打印一些内容:

Nothing to change
关于程序终止 销毁按相反的顺序进行,最后创建的
change
'd对象首先被销毁

I am destroying an A
I am destroying an A3
I am destroying an A2 with: 400
I am destroying an A1 with: 100
我正在销毁一个BigA
打印了两次,但是
我刚刚构建了一个BigA
——只有一次。后者是因为您没有采用
const&BigA
BigA
的复制构造函数(上面也指出了这一点)

回答你的问题 是的,复制构造函数在这里调用是正确的
A cdata2=data2CDATA 2
以前未初始化。这是一个解释得很好的案例

如果你这样修改代码

A cdata2;
cdata2 = data2;
您将看到预期的任务:

I am constructing an A1 with: 10
I am constructing an A2 with: 20
I am constructing an A3
I am constructing an A
I am performing a stupid assignment between As

感谢你的超级分析性解释,这是我能问的更多。然而,作业操作员(或者我认为是这样)出现了一个问题(我编辑了我的问题),如果你也能解释一下,我将不胜感激;有趣的是,初始化顺序不依赖于初始化列表序列,而是依赖于初始化列表序列。类可以有多个构造函数,并且唯一的析构函数应该以明确的相反顺序销毁字段。
A cdata2;
cdata2 = data2;
I am constructing an A1 with: 10
I am constructing an A2 with: 20
I am constructing an A3
I am constructing an A
I am performing a stupid assignment between As