有人可以解释为什么当c
完成构建时,b
(c成员)的析构函数被调用,而d
被解析 - 正如预期的那样 - c
析构函数被称为?
#include <iostream>
using namespace std;
class A
{
public:
int a, b;
};
class B
{
public:
A* array[10];
B()
{
for(int i = 0 ; i < 10 ; i++)
array[i] = new A();
}
~B()
{
for(int i = 0 ; i < 10 ; i++)
delete array[i];
}
};
class C
{
public:
B b;
B* d;
C()
{
b = B();
}
~C()
{
delete d;
}
};
int main()
{
B b = B();
C c = C();
cout << "Ashlamish" << endl;
system("pause");
return 0;
}
答案 0 :(得分:2)
因为在C的构造函数中,您在行c = B();
中创建了一个临时B对象,当赋值完成时,该临时对象正在被销毁。
答案 1 :(得分:2)
在b = B()
中,您正在构建一个新的B类临时实例,为b分配一个副本,然后对该临时实例进行解析。
答案 2 :(得分:2)
我想你想宣布这样的:
C c;
这将构造一个名为c的对象,它将在作用域出口处被破坏。 另一方面,你有什么;
C c = C();
将构造一个C类型的匿名对象,使用它复制构造c并立即销毁匿名对象。 c将在范围的最后被破坏。
答案 3 :(得分:2)
在C的构造函数中,你有
b = B();
这是做什么的:
要在C的构造函数中修复此使用初始化列表,如下所示:
C() : b()
{ }
或者只是将构造函数留空,这样它将使用默认构造函数。
答案 4 :(得分:1)
b = B();
构造函数中的行C
实例化B
类型的新对象,并使用B
的复制构造函数在C::b
中复制此类对象
当C
构造函数返回b
时不会被销毁,但用于调用B
的复制构造函数的b
临时对象是。
你可以删除这样的指令,以避免实例化B
临时,在这种情况下,b将只使用默认构造函数构建。
答案 5 :(得分:1)
临时B的析构函数称为(b = B();
),而不是成员b
。可以删除此行,因为b
已经在隐式初始化列表
答案 6 :(得分:1)
你在这里犯了一个重大的罪 - 不遵守rule of 3。
你的B需要一个析构函数,但不实现复制和赋值。
然后继续通过实际执行任务来加剧错误。
您还会继续删除未初始化的指针。 (如果d为NULL,那就没关系了,但没有理由这样做。)
您还需要实现复制构造,尤其是您的编译器可能会选择将其用于上述构造,尽管它可能实际上不会这样做。