2011-06-10 92 views
5

我正在實現一個二進制堆類。堆被實現爲動態分配的數組。堆類有成員的身份,大小和一個指向數組的指針,如:構造函數中的malloc

class Heap 
{ 
    private: 
     Heap* H; 
     int capacity; //Size of the array. 
     int size; //Number of elements currently in the array 
     ElementType* Elements; //Pointer to the array of size (capacity+1) 

     //I've omitted the rest of the class. 
}; 

我construcor看起來是這樣的:

Heap::Heap (int maxElements) 
{ 
    H = (Heap*) malloc (sizeof (Heap)); 
    H -> Elements = (ElementType*) malloc ((maxElements+1)*sizeof (ElementType)); 
    H -> Elements[0] = DUMMY_VALUE; //Dummy value 
    H -> capacity = maxElements; 
    H -> size = 0; 
} 

由於我mallocing兩次,並在構造函數中提領兩個指針,我應該檢查它是否成功。但如果失敗了,我該怎麼辦?構造函數本身不能返回任何東西來表明它失敗。完全避免構造函數中的malloc是不錯的編程習慣嗎?

+2

你好,@Sahil!歡迎來到Stack Overflow。感謝您粘貼與您的問題相關的代碼,但請在提出下一個問題時將其格式化爲代碼(每行縮進四個空格,或使用標有'{}'的按鈕)。另外,我不認爲你需要你的'H'成員變量。當你的構造函數被輸入時,'Heap'對象的空間已經被分配了。你只需要爲'Elements'數組分配空間。 – 2011-06-10 19:36:36

+0

我不明白爲什麼你的Heap對象有一個指向另一個Heap對象的指針,特別是當你不使用你正在構造的對象的成員時。我會失去第一個'malloc'並直接使用你的對象的成員。 – 2011-06-10 19:39:43

+0

事實上,讓指針「H」指向構造函數沒有運行的內存是非常糟糕的做法。我敢打賭,解引用'H'調用未定義的行爲。爲什麼不直接在你的課堂上儲存'capacity','size'和'Elements'? – Vlad 2011-06-10 19:41:14

回答

14

首先,你需要你Heap對象內Heap*成員變量,你當然不應該爲它在Heap構造函數分配內存 - 這只是自找麻煩。您也不應該以H->Elements訪問您的成員變量,而應該簡單地訪問Elements

您需要分配的唯一東西是Elements數組。

關於處理分配失敗,構造函數應通過異常指示失敗。甚至有一個標準的異常類型,std::bad_alloc通常用於指示分配內存失敗。

例如:

#include <stdexcept> // for std::bad_alloc 
... 
Heap::Heap (int maxElements) 
{ 
    Elements = (ElementType*) malloc ((maxElements+1)*sizeof (ElementType)); 
    if (Elements == NULL) 
     throw std::bad_alloc("Failed to allocate memory"); 
    ... 
} 

更妙的是,使用new而不是malloc分配內存。如果分配內存失敗,new將自動拋出類型爲std::bad_alloc的異常。

例子:

Heap::Heap (int maxElements) 
{ 
    Elements = new ElementType[maxElements + 1]; // throws std::bad_alloc on failure 
    ... 
} 

注:如果您使用new分配對象,則必須使用delete來釋放它,而不是free。 (更正:在上面的示例中,您使用的是新的陣列形式,new[],因此您應該調用刪除的陣列形式,delete[])。

最後,你有沒有看到如何ElementType聲明,但如果它是具有非默認構造函數/析構型(或者如果它,這意味着它有可能成爲這種類型的模板參數),你使用new而不是malloc分配它時,因爲malloc將不會調用構造函數(和free將不會調用析構函數)。一般來說,最好總是在C++中使用newdelete,而不是mallocfree

+0

@Roddy但它不是'new heap',它是'Heap * H =(Heap *)malloc(sizeof(Heap))' - 構造函數不會被調用;-) – 2011-06-10 19:46:53

+1

如果使用'new [] ',不要使用'delete' - 使用'delete []'! – 2011-06-10 19:49:07

+0

@Khaled:Roddy在評論我最初推薦用'H = new Heap'替換'H =(堆*)malloc(sizeof(堆))'的答案。那是在我意識到這是多麼錯誤之前... – HighCommander4 2011-06-10 19:50:05

1

你是在自己的構造函數中分配對象嗎?無厘頭:

H = (Heap*) malloc (sizeof (Heap)); 

構造是由new操作者調用,內​​存分配之後。如果你想創建一個單 - 使用方法,實例化對象的靜態方法,並調用

class Heap{ 
public: 
    static Heap* Get(); 
private: 
    Heap(); 
    static Heap* H; 
} 

Heap *Heap::H = 0; 

Heap * Heap::Get() 
{ 
    if (!H) 
     H = new (Heap); 
    return H; 
} 

Heap::Heap() 
{ 
    // whatever else 
} 

你的問題:malloc是一個C函數。在C++中 - 使用new。你不需要檢查返回值,那麼,new將在失敗時引發異常。

+1

是的,這一點沒有意義。但這不是他的問題的答案,只是你的一個有用的觀察。也許這應該是一個評論而不是答案? – 2011-06-10 19:37:41

5

你應該學習,其中第一個就是一些基本的C++「道路規則」:

使用標準模板庫!

class Heap { 
    private: 
    std::vector<ElementType> elements; 
} 

而你的構造函數?你不需要一個。

一般來說,任何在C++中使用malloc()free()都是'代碼異味'。這是一個確定的方式,結束了錯誤構造的對象,緩衝區溢出和內存泄漏。使用newdelete,最好使用智能指針。

或者更好。只要可能就讓你的對象靜態構造。