是的它会泄漏内存.当构造函数抛出时,不会调用析构函数(在这种情况下,您不会显示释放动态分配对象的析构函数,但假设您有一个析构函数).
这是使用智能指针的一个主要原因 - 因为聪明的poitners是完全成熟的对象,它们将在异常的堆栈放松期间调用析构函数,并有机会释放内存.
如果您使用Boost的scoped_ptr <>模板之类的东西,您的类可能看起来更像:
class base{ int a; scoped_ptrpint; someclass objsomeclass; scoped_ptr psomeclass; base() : pint( new int), objsomeclass( someclass()), psomeclass( new someclass()) { throw "constructor failed"; a = 43; } }
而且你没有内存泄漏(默认的dtor也会清理动态内存分配).
总结(并希望这也回答了有关的问题
base* temp = new base();
声明):
当在构造函数中抛出异常时,在正确处理可能在对象的中止构造中发生的资源分配方面,您应该注意以下几点:
将不会调用正在构造的对象的析构函数.
将调用该对象类中包含的成员对象的析构函数
将释放正在构造的对象的内存.
这意味着如果您的对象拥有资源,您可以使用两种方法来清理构造函数抛出时可能已经获取的那些资源:
捕获异常,释放资源,然后重新抛出.这可能很难纠正并且可能成为维护问题.
使用对象来管理资源生命周期(RAII)并将这些对象用作成员.当对象的构造函数抛出异常时,成员对象将调用析构函数,并有机会释放他们负责的生命周期的资源.
KTC.. 5
两个新的都将被泄露.
将堆创建的对象的地址分配给命名的智能指针,以便在抛出异常时获取调用的智能指针析构函数中删除它 - (RAII).
class base { int a; boost::shared_ptrpint; someclass objsomeclass; boost::shared_ptr psomeclass; base() : objsomeclass( someclass() ), boost::shared_ptr psomeclass( new someclass() ), boost::shared_ptr pint( new int() ) { throw "constructor failed"; a = 43; } };
现在,当构造函数中抛出异常时,当堆栈展开时,将调用psomeclass&pint析构函数,这些析构函数将释放已分配的内存.
int main(){ base *temp = new base(); }
对于使用(非plcaement)new的普通内存分配,如果构造函数抛出异常,则由operator new分配的内存将自动释放.就为什么要解放个别成员而言(响应对Mike B的回答的评论),自动释放仅适用于在新分配的对象的构造函数中抛出异常,而不是在其他情况下.此外,释放的内存是为对象成员分配的内存,而不是您在构造函数中分配的任何内存.即它将释放成员变量a,pint,objsomeclass和psomeclass的内存,但不释放从new someclass()和new int()分配的内存.
是的它会泄漏内存.当构造函数抛出时,不会调用析构函数(在这种情况下,您不会显示释放动态分配对象的析构函数,但假设您有一个析构函数).
这是使用智能指针的一个主要原因 - 因为聪明的poitners是完全成熟的对象,它们将在异常的堆栈放松期间调用析构函数,并有机会释放内存.
如果您使用Boost的scoped_ptr <>模板之类的东西,您的类可能看起来更像:
class base{ int a; scoped_ptrpint; someclass objsomeclass; scoped_ptr psomeclass; base() : pint( new int), objsomeclass( someclass()), psomeclass( new someclass()) { throw "constructor failed"; a = 43; } }
而且你没有内存泄漏(默认的dtor也会清理动态内存分配).
总结(并希望这也回答了有关的问题
base* temp = new base();
声明):
当在构造函数中抛出异常时,在正确处理可能在对象的中止构造中发生的资源分配方面,您应该注意以下几点:
将不会调用正在构造的对象的析构函数.
将调用该对象类中包含的成员对象的析构函数
将释放正在构造的对象的内存.
这意味着如果您的对象拥有资源,您可以使用两种方法来清理构造函数抛出时可能已经获取的那些资源:
捕获异常,释放资源,然后重新抛出.这可能很难纠正并且可能成为维护问题.
使用对象来管理资源生命周期(RAII)并将这些对象用作成员.当对象的构造函数抛出异常时,成员对象将调用析构函数,并有机会释放他们负责的生命周期的资源.
两个新的都将被泄露.
将堆创建的对象的地址分配给命名的智能指针,以便在抛出异常时获取调用的智能指针析构函数中删除它 - (RAII).
class base { int a; boost::shared_ptrpint; someclass objsomeclass; boost::shared_ptr psomeclass; base() : objsomeclass( someclass() ), boost::shared_ptr psomeclass( new someclass() ), boost::shared_ptr pint( new int() ) { throw "constructor failed"; a = 43; } };
现在,当构造函数中抛出异常时,当堆栈展开时,将调用psomeclass&pint析构函数,这些析构函数将释放已分配的内存.
int main(){ base *temp = new base(); }
对于使用(非plcaement)new的普通内存分配,如果构造函数抛出异常,则由operator new分配的内存将自动释放.就为什么要解放个别成员而言(响应对Mike B的回答的评论),自动释放仅适用于在新分配的对象的构造函数中抛出异常,而不是在其他情况下.此外,释放的内存是为对象成员分配的内存,而不是您在构造函数中分配的任何内存.即它将释放成员变量a,pint,objsomeclass和psomeclass的内存,但不释放从new someclass()和new int()分配的内存.