当构造函数必须创建另一个类的新对象时,它是如何工作的?

时间:2016-09-04 16:23:54

标签: c++

我有这个代码,我试图理解编译器的工作原理:

#include <iostream>
using namespace std;
class Block
{
    int data;

public:
    Block(int i = 10)
        : data(i)
    { 
        cout << "I just created a Block " << endl;
    }
    ~Block()
    {
        cout << "I will destroy a Block with " << data << endl;
    }
    void inc()
    {
        data++;
    }
};
class A
{
    Block& block1;
    Block block2;

public:
    A(Block& blk)
        : block1(blk)
        , block2(blk)
    {
        cout << "I just created an A " << endl;
    }
    A(const A& a)
        : block1(a.block1)
        , block2(a.block2)
    {
        cout << "I just created an A by copying but I will also do bad things" << endl;
        block1.inc();
        block2.inc();
    }
    ~A()
    {
        cout << "I will destroy an A " << endl;
    }
    void inc()
    {
        block1.inc();
        block2.inc();
    }
};
class Fat
{
    A a;
    A& ra;
    A* pa;

public:
    Fat(A& da)
        : a(da)
        , ra(da)
    {
        pa = new A(da);
        cout << "Fat just created !" << endl;
    }
    ~Fat()
    {
        delete pa;
        cout << "Fat to be destroyed !" << endl;
    }
    void inc()
    {
        a.inc();
        ra.inc();
        pa->inc();
    }
};
int main()
{
    Block block;
    A a(block);
    Fat fat(a);
    fat.inc();
    return 0;
}

创建A对象时,是创建新块还是使用现有块? 为什么不运行块的构造函数?

程序的输出是:

I just created a Block 
I just created an A 
I just created an A by copying but I will also do bad things
I just created an A by copying but I will also do bad things
Fat just created !
I will destroy an A 
I will destroy a Block with 12
Fat to be destroyed !
I will destroy an A 
I will destroy a Block with 12
I will destroy an A 
I will destroy a Block with 11
I will destroy a Block with 15

2 个答案:

答案 0 :(得分:2)

你可以用更简单的代码证明这一点。

#include <iostream>

class Noisy
{
public:
    Noisy()
        { std::cout << "Noisy default construct\n"; }
    ~Noisy()
        { std::cout << "Noisy destroy\n"; }
};

int main()
{
    Noisy noisy1;
    Noisy noisy2(noisy1);
}

输出

Noisy default construct
Noisy destroy
Noisy destroy

请注意,显然,只构建了一个对象,但有两个被销毁。这种明显不一致的原因是因为我们没有记录所有或我们的构造函数。有一个隐式生成的复制构造函数,我们在这里用来构造noisy2

Noisy noisy2(noisy1);

如果我们自己定义复制构造函数,

#include <iostream>

class Noisy
{
public:
    Noisy()
        { std::cout << "Noisy default construct\n"; }
    Noisy(Noisy const&)
        { std::cout << "Noisy copy construct\n"; }
    ~Noisy()
        { std::cout << "Noisy destroy\n"; }
};

int main()
{
    Noisy noisy1;
    Noisy noisy2(noisy1);
}

输出:

Noisy default construct
Noisy copy construct
Noisy destroy
Noisy destroy

您可以看到构造了两个对象,只是使用不同的构造函数。如果您对各种类进行此操作,您应该会看到类似的结果。不会记录您的引用,也不会记录构造函数或析构函数,因为它们不是对象。

答案 1 :(得分:2)

  

创建A对象时,是创建新块还是使用现有块?为什么不运行块的构造函数?

查看actualRow构造函数:

A

A(Block& blk) : block1(blk) , block2(blk) { } referenceblock1个对象。所以它引用了已经创建的Block变量,并且它不会创建另一个变量。因此,在这种情况下不会调用构造函数。

对于不是参考的blk,情况并非如此。在这种情况下,确实会创建一个 new 对象block2,但使用copy constructor

您在Block课程中定义的内容是默认构造函数。 当从同一个类的另一个对象开始创建类实例时,将调用复制构造函数(注意:不是默认构造函数)。

复制构造函数由编译器隐式定义,除非您自己定义。

例如:

Block

这就是为什么您的代码只调用类class Block { public: Block(const Block& other) : data(oth.data) { std::cout << "Invoked copy 'ctor" << std::endl; } // ... other stuff }; 默认构造函数的原因。