2

假设我们有如下所示的类:类指针构件和异常处理

实施例1

int main() { 
    A a; 
    throw "error"; 

    return 0; 
} 
:其利用它

class A { 
    public: 
     A(); 
     ~A(); 
     void foo(); 
     int* pointer; 
}; 

A::A() { 
    pointer = new int; 
} 

A::~A() { 
    delete pointer; 
} 

A::foo() { 
    throw "error"; 
} 

而以下的实施例

实施例2

int main() { 
    A a; 
    a.foo(); 

    return 0; 
} 

在这两种情况下,会出现内存泄漏,至于析构函数永远不会由于未处理的异常被调用。

我的问题是责任是否与类的用户通过处理异常来调用析构函数有关:在第一个例子中,异常与类无关,所以我认为责任在于该类的用户,但在第二个例子中,类本身抛出错误 - 是否仍然由类的用户来确保正确处理异常,还是仅仅是该类本身的糟糕设计?

回答

3
void throw(); 

这不会编译。 throw是保留关键字。

忽略这个细节,暂时,你的初始假设并不完全正确。

在这种情况下,异常不会被捕获,程序将终止,因此内存泄漏是学术性的。

但是,如果在范围内有一个try/catch区块,则会捕获该异常,在这两种情况下都不会发生内存泄漏。在这两个示例中,a对象都已完全构建。因此,抛出的异常将会破坏a,并调用其析构函数。

抛出异常将展开堆栈,直到捕获到异常为止,并且作为该进程的一部分,销毁本地作用域中的所有对象,直到捕获到异常。

所以,这是一个有争议的问题。没有内存泄漏,只要异常最终被捕获,没有人需要担心任何事情。

您显示的类大部分符合RAII原则(需要复制构造函数和赋值运算符来包装松散结束)。该类负责的唯一的事情将是如果抛出异常在构造函数,不管构造函数已分配需要清理。

+0

是的,这是真的,稍加修改。 –

+0

修正了void throw();错误。感谢您指出:) – p0llard

1

这是非常不相关的。存在“内存泄漏”的唯一原因是程序将结束,通常会清理内存。

在任何情况下,如果程序因未处理的异常而退出,那不是类的问题。想象一下,如果你有100个班,所有这些都需要关心一个功能(main)是否未能处理异常。