我想知道为什么我得到3x~C()。我知道前5个C()来自前2个声明,数组声明使用构造函数2次,然后是另一个声明。之后,为什么我得到3而不是1个析构函数调用?
#include <iostream>
using namespace std;
class C
{
public:
C() {cout<< "C() ";}
~C() {cout<< "~C() ";}
private:
int i;
};
int main(){
C c1;
C* p1= new C;
{
C c[2];
C* p2 = new C;
delete p2;
}
C c[2];
delete p1;
return 0;
}
//C() C() C() C() C() ~C() ~C() ~C() C() C() ~C() ~C() ~C() ~C()
答案 0 :(得分:2)
我将分解代码并使用构造/销毁调用对其进行注释:
#include <iostream>
using namespace std;
class C
{
public:
C() {cout<< "C() ";}
~C() {cout<< "~C() ";}
private:
int i;
};
int main(){
C c1; // C()
C* p1= new C; // C()
{
C c[2]; // C() C() - because you constructed two C objects with this array
C* p2 = new C; // C()
delete p2; // ~C()
} // ~C() ~C() because the {} block ends, which means that local objects to that scope are destructed
C c[2] ; // C() C() because you constructed two more
delete p1; // ~C() because you're explicitly destructing
return 0; // ~C() ~C() ~C() because of the c1 object and the c[2] array being destructed
}
所以最终会发生这种情况:
C() // c1 created
C() // p1 created
C() // c[2] created
C() // c[2] created
C() // p2 created
~C() // delete p2
~C() // c[2] in {} destroyed by end of scope
~C() // c[2] in {} destroyed by end of scope
C() // c[2] created
C() // c[2] created
~C() // delete p1
~C() // c[2] destroyed at end of program
~C() // c[2] destroyed at end of program
~C() // c1 destroyed at end of program
答案 1 :(得分:0)
删除对象指针时,或者当堆栈对象超出范围时,将调用析构函数。以下是您的代码中逐行发生的事情:
int main(){
C c1;
// C() (1 stack object created in main scope(a) )
C* p1= new C;
// C()
{
C c[2];
// C() C() (2 stack objects created in inner scope)
C* p2 = new C;
// C()
delete p2;
// ~C()
}
// ~C() ~C() (the array of 2 objects went out of scope, so they got destructed)
C c[2];
// C() C() (2 stack objects created in main scope, (b) and (c))
delete p1;
// ~C()
return 0;
// ~C() ~C() ~C() (3 stack objects destructed in main scope (a), (b) and (c))
}
如果您更改类以保留每个对象的唯一ID,则可以在此处了解更好的内容:
class C
{
public:
C()
: i (newID()) {
cout<< "C#" << i << "()";
}
~C() {
cout<< "~C#" << i << "()";
}
private:
int newID() {
static int counter = 0;
return counter++;
}
const int i;
};
输出:
C#0 C#1 C#2 C#3 C#4~C#4~C#3~C#2 C#5 C#6~C#1~C#6~C#5~C #0
答案 2 :(得分:0)
C c1
ctr叫了1次
C* p1= new C;
ctr叫了1次
C c[2];
ctr打了两次电话
C* p2 = new C;
ctr叫了1次
delete p2;
dtr叫了一次
c
超出范围,dtr调用2次
C c[2];
ctr打了两次电话
delete p1;
dtr叫了一次
c1
超出范围; dtr叫1次
c
运行范围otu,dtr调用2次
现在,问题出在哪里?
答案 3 :(得分:0)
前5个构造函数调用是明确的。然后有3个析构函数调用。第一个c
数组在块中声明:
{
C c[2]
//...
} // objects in c are destroyed
当剩下块时,通过调用它们的析构函数来销毁在块内非动态创建的所有对象。因此,有来自delete p2
的第一个析构函数调用,然后是另外两个析构函数调用,用于销毁数组中包含的两个对象。对于最后的四个析构函数调用也是如此:第一个析构函数从您的delete p1
调用os,其他三个析构函数调用是在块外声明的C c[2]
并用于销毁{ {1}}对象。
答案 4 :(得分:0)
这可能有助于您理解任何非动态(malloc / new)堆分配对象超出范围时,它都会被销毁!
#include <iostream>
using namespace std;
class C
{
public:
C() {cout<< "C() ";}
~C() {cout<< "~C() ";}
private:
int i;
};
int main(){
C c1; // Construct c1
cout << "--------------";
C* p1= new C; // Construct p1
{
cout << "--------------";
C c[2]; // Construct 2 objects c[2]
cout << "--------------";
C* p2 = new C; // Construct p2
cout << "--------------";
delete p2; // Destruct p2
} // Destructs 2 objects c[2]
cout << "--------------";
C c[2]; // builds 2 objects
cout << "--------------";
delete p1;
// p1 is destructed
return 0;
} // two objects in c[2] are destructed, c1 is also destructed
输出:
C() --------------C() --------------C() C() --------------C() --------------
~C() ~C() ~C() --------------C() C() --------------~C() ~C() ~C() ~C()