在完成编程任务时,我似乎对基本的C ++概念感到磕磕绊绊。我在我的程序中发现了这个错误,这是因为我的析构函数运行的次数超出了我的预期。这是一个代码示例,演示了我做错了什么,直到最基本的内容。
#include <iostream>
using namespace std;
class A
{
public:
A(int num)
{
number = num;
cout << "A constructed with number " << number << ".\n";
}
~A()
{
cout << "A destructed with number " << number << ".\n";
}
private:
int number;
};
class B
{
public:
B(A pa)
: a(pa)
{
cout << "B constructor run.\n";
}
~B()
{
cout << "B destructor run.\n";
}
private:
A a;
};
int main()
{
A foo(7);
{
B bar(foo);
}
//Pause the program.
system("pause");
}
我期望发生的是A foo(7);
为名为A
的{{1}}对象分配堆栈空间并调用构造函数,传递foo
。它将7
分配给7
并打印输出,指示构造函数已运行。现在number
为名为B bar(foo);
的{{1}}对象分配堆栈空间并调用构造函数,按值传递B
,这只是{{1}的容器}。构造函数将传递给它的bar
参数分配给它自己的私有数据成员foo
,并将输出打印到屏幕上。
现在,当int
超出结束大括号的范围时,我希望调用A
的析构函数,将输出打印到屏幕,然后调用析构函数以获取其数据成员,即a
。该析构函数将输出打印到屏幕,并丢弃它所包含的bar
。
我期望输出应该是:
bar
实际输出:
A a
造成这种额外破坏的原因是什么?
答案 0 :(得分:3)
您的B
构造函数按值获取A
对象,这意味着foo
被复制到参数pa
中,然后将其复制到成员a
}。编译器已经能够忽略其中一个副本(构造函数的参数),但另一个副本不能被省略,并且你有第二个A
对象被破坏。
答案 1 :(得分:2)
显然它来自会员数据A a; B类。我猜你的疑问是为什么不看A的任何构造输出,因为它是用A类的默认copy-ctor构造的,最好为A类添加一个copy-ctor,这样你就会看到构造过程
A(const A& a)
{
number = a.number;
cout << "A copy-constructed with number " << number << ".\n";
}
答案 2 :(得分:1)
当人们变得可爱时,我讨厌它&#34; foo&#34;和&#34; bar&#34;。
但我看到了两个&#34; A&#34;正在构建 - 一个明确地,另一个隐含地由&#34; B&#34;。并且有两个析构函数被调用。
对这张照片不喜欢什么;)?
答案 3 :(得分:0)
因为在B类中,有一个成员A a
所以要破坏B对象,首先调用其成员的析构函数。