我有这个代码,我试图理解编译器的工作原理:
#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
答案 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)
{
}
是reference到block1
个对象。所以它引用了已经创建的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
};
的默认构造函数的原因。