我定义了一个类foo,如下所示:
class foo {
private:
static int objcnt;
public:
foo() {
if(objcnt==8)
throw outOfMemory("No more space!");
else
objcnt++;
}
class outOfMemory {
public:
outOfMemory(char* msg) { cout << msg << endl;}
};
~foo() { cout << "Deleting foo." << endl; objcnt--;}
};
int foo::objcnt = 0;下面是主要函数:
int main() {
try {
foo* p = new foo[3];
cout << "p in try " << p << endl;
foo* q = new foo[7];
}catch(foo::outOfMemory& o) {
cout << "Out-of-memory Exception Caught." << endl;
}
}很明显,"foo* q= new foo7;“这一行只成功创建了5个对象,并且在第6个对象上抛出了内存不足异常。但事实证明,只有5次析构函数调用,并且没有为存储在p指向的位置的3个对象的数组调用析构函数。所以我想知道为什么?为什么程序只调用这5个对象的析构函数?
发布于 2011-11-17 21:57:42
析构函数只为完全构造的对象调用-这些对象的构造函数正常完成。只有在new[]执行过程中抛出异常时,这种情况才会自动发生。因此,在您的示例中,将为在q = new foo[7]运行期间完全构造的五个对象运行析构函数。
由于p所指向的数组的new[]已成功完成,因此该数组现在被处理到您的代码中,并且C++运行时不再关心它-除非您执行delete[] p,否则不会运行析构函数。
发布于 2011-11-17 23:41:38
当您在堆上声明数组时,您将获得预期的行为:
int main()
{
try
{
foo p[3];
cout << "p in try " << p << endl;
foo q[7];
}
catch(foo::outOfMemory& o)
{
cout << "Out-of-memory Exception Caught." << endl;
}
}在您的代码中,只有指针是局部自动变量。当堆栈展开时,指针没有任何相关的清理。正如其他人所指出的,这就是为什么在C++代码中通常没有原始指针的原因,它们通常被包装在一个类对象中,该类对象使用构造函数/析构函数来控制它们的生命周期(智能指针/容器)。
顺便说一句。使用std::vector通常比使用原始数组更好(在C++11中,如果您有固定大小的数组,std::array也很有用)。这是因为堆栈的大小有限,而这些对象将大部分数据放在堆中。这些类对象提供的额外方法使它们更易于在其余代码中处理,如果您一定要将旧式数组指针传递给C函数,则很容易获得这些方法。
int main()
{
try
{
std::vector<foo> p(3);
cout << "p in try " << p << endl;
std::vector<foo> q(7);
// Now you can pass p/q to function much easier.
}
catch(foo::outOfMemory& o)
{
cout << "Out-of-memory Exception Caught." << endl;
}
}https://stackoverflow.com/questions/8168203
复制相似问题