簡體   English   中英

在構造函數中拋出C ++ bad_alloc

[英]C++ bad_alloc thrown in a constructor

當在構造器中拋出bad_alloc異常(在該構造器中創建多個對象)時,必須執行清理內存的操作。 例如

class Object
{
   private:
     A * a;
     B  * b;

 public:

   Object()
   {
       a= new A();
       b= new B(); //So if a bad_alloc is called here, how is a deleted???
   }
} 

我的直覺是將對new的每個調用放在單獨的try catch bloc中,並刪除以前為其調用new所有對象,但這太冗長了(第一個try bloc不調用析構函數,第二個類調用第一個,第三個調用前兩個等)。 我的問題是:最常見的處理方式是什么?

另外,可以說類對象包含一個不是用new創建的對象(因為它在堆棧上),它的析構函數會自動調用嗎?

您要使用智能指針:

class Object {
    std::unique_ptr<A> a;
    std::unique_ptr<B> b;

public:
    Object() : a(make_unique<A>()), b(make_unique<B>()) {}
}

首先,我修復了您的代碼,因為這是一個C ++問題,因此必須將其編寫為C ++。 構造函數可能會因bad_alloc之外的異常而失敗。

您有以下選擇:

  • 不存儲指針,但存儲對象。 這些是自動構造的(或通過初始化列表),如果創建,則將自動清除。 這可能會更好,但是意味着它們需要完全定義,即包括其標頭,並且您可能試圖隱藏實現細節/分離。

  • 存儲某種智能指針,例如unique_ptr ,它實際上是一個對象,因此像對象一樣被清理,如果有則刪除基礎指針。

  • 將常規指針存儲在您的類中,但在構造函數期間使用unique_ptr (如果無法使用unique_ptr則使用auto_ptr ),最后,當您知道一切都已正確構建時,可以將智能指針釋放到成員變量中。

后一種解決方案如下所示:

 // header file
 //
class A; // implementation hidden on purpose
class B; // ditto

class Object
{
   private:
      A * a;
      B * b;

   public:
     Object();
     ~Object();

    private:

 // if not using C++11 do not put in =delete but still declare these

    Object( const Object & ) = delete;
    Object& operator=( const Object & ) = delete;

};

// cpp file

#include "object.h"
#include "a.h"
#include "b.h"

Object::Object()
   : a( nullptr ), // use NULL or 0 if nullptr not available
     b( nullptr )
{
    std::unique_ptr< A > pa( new A ); // might throw
    std::unique_ptr< B > pb( new B ); // might throw (1)

    a = pa.release(); // cannot throw
    b = pb.release(); 
}

Object::~Object()
{
     delete b;
     delete a;
}

(1)如果它拋出了局部的pa ,則將調用其析構函數,這將刪除使用new創建的指針。

注意:如果您沒有unique_ptr可用,則auto_ptr也可以在此處使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM