2009-04-24 131 views
2

只是一個簡單的問題:RAII和未初始化值

,如果我有一個簡單的載體類:

class Vector 
{ 
public: 
    float x; 
    float y; 
    float z; 
}; 

犯規的RAII的概念應用在這裏呢?即提供一個構造函數將所有值初始化爲某些值(以防止使用未初始化的值)。

編輯或提供一個構造函數,明確要求用戶在實例化對象之前初始化成員變量。

class Vector 
{ 
public: 
    float x; 
    float y; 
    float z; 
public: 
    Vector(float x_, float y_, float z_) 
    : x(x_), y(y_), z(z_) 
    { // Code to check pre-condition; } 
}; 

應該RAII被用來幫助程序員忘記使用數據之前初始化值,或者是開發商的責任?

或者是看RAII的錯誤方式?

我故意讓這個例子很簡單。我真正的問題是回答,例如,複合材料類,如:

class VectorField 
{ 
public: 
    Vector top; 
    Vector bottom; 
    Vector back; 

    // a lot more! 
}; 

正如你所看到的......如果我不得不寫一個構造函數初始化每一個成員,這是相當繁瑣的。

想法?

回答

6

RAII中的「R」代表資源。並非一切都是資源。

許多類,如std :: vector,都是自我初始化的。你不需要擔心這些。

POD類型是而不是自我初始化,因此將它們初始化爲一些有用的值是有意義的。

3

我不會說RAII適用於此。請記住這些字母代表的是:資源獲取是初始化。您沒有資源被收購,因此RAII不適用。

您可以提供一個默認構造函數Vector;這將消除您明確初始化VectorField的所有成員的需要。編譯器會插入代碼爲你做。

4

由於您Vector類中的字段是內置的類型,以確保它們被初始化,你將不得不做,在一個構造函數:現在

class Vector 
{ 
public: 
    float x; 
    float y; 
    float z; 

    Vector() : x(0.0), y(0.0), z(0.0) {} 
}; 

,如果你的領域是類如果它們寫得很好,它們應該自動初始化(如果需要的話,自行清理)。

以某種方式,這與RAII類似並且與RAII相關,因爲RAII意味着資源(內存,句柄,任何)由對象自動獲取和清理。

0

如果你不寫構造函數,編譯器會生成一個默認構造你,並設置這些值設置爲默認(未初始化值)。提供一個默認的構造函數,並初始化值,這將是您最好的方式來做到這一點。我不認爲這樣做太複雜。不要太懶惰:-)

+3

如果值是未初始化的,那麼我不認爲這是恰當的說編譯器生成的構造函數具有「將這些值設置爲默認值」。它沒有把它們設置爲任何東西;這就是爲什麼他們未初始化。 – 2009-04-24 02:56:27

3

當您需要執行顯式清理並且希望在清除另一個對象的同時發生清理時,可以使用RAII模式。這可能發生在內存分配/釋放,關鍵部分進入/退出,數據庫連接等等。在您的示例中,「浮動」會自動清除,因此您不必擔心它們。但是,假設您有以下函數來調用以獲取向量:

Vector* getMeAVector() { 
    Vector *v = new Vector(); 
    // do something 
    return v; 
} 

並且說這是調用者的責任,即刪除返回的向量。如果您按以下方式調用此代碼:

Vector *v = getMeAVector(); 
// do some stuff with v 
delete v; 

您必須記住釋放該向量。如果「stuff」是一段很長的代碼,可能會拋出一個異常,或者在那裏有一堆return語句,那麼你必須在每個退出點釋放vector。即使你這樣做了,通過添加另一個「返回」語句或調用某個引發異常的庫來維護代碼的人可能不會。相反,你可以這樣寫一個類:

​​

然後,你可以得到向量像這樣:

Vector *v = getMeAVector(); 
AutoVector av(v); 
// do lots of complicated stuff including throwing exceptions, multiple returns, etc. 

那麼你不必擔心刪除向量了,因爲當av超出範圍將自動刪除。如果需要,您可以編寫一個小宏使「AutoVector av(v)」語法更好一些。

這是一個人爲的例子,但是如果周圍的代碼很複雜,或者它可以拋出異常,或者有人在中間添加「return」語句,那麼「AutoVector」將自動釋放內存。

你可以做同樣的事情用一個「自動」級進入其構造函數和出口在其析構函數的一個關鍵部分,等