2017-08-29 67 views
0

假設我有一個類A,它使用動態內存分配,如數組或矩陣。在創建對象A的過程中,通過構造函數傳遞參數來確定分配多少內存空間。處理無法以預定方式創建的對象,C++

class A 
{ 
    int * ptr; 
    int size; 
    void allocate() noexcept; 
    void destroy() noexcept; 
    public: 
    A(int) noexcept; 
    ~A() noexept; 
} 
void A::destroy() noexcept 
{ 
    if(ptr!=nullptr) 
    delete [] ptr; 
} 
A::~A() noexcept 
{ destroy();} 
void A::allocate() try 
{ 
    ptr = new int[n]; 
} 
catch (std::bad_alloc & ex) 
{ 
    std::cerr << ex.what(); 
    destroy(); 
} 
A::A(int n) noexcept : size(n) { allocate(); }; 

這些東西是一種很好的做法,設計明智嗎?對於無法以預定方式創建的對象會發生什麼情況?它會像「殭屍」一樣「活着」嗎?還是會被摧毀?

在矩陣方案中該怎麼辦,矩陣分配多個新的陳述?

智能指針,STL和那種東西不是這裏的一個選項。

讀我:這個班是純粹爲此類問題而設的示範班。它並不遵循0/3/5的規則,因爲編寫代碼太多隻是針對一個問題,對於這個問題並不重要。關於這些問題已經存在一堆問題。

+1

爲什麼不讓應該扔掉的東西扔掉? – juanchopanza

+1

爲什麼在失敗的分配中調用'destroy'?未能分配意味着你沒有任何東西來「刪除」。 –

+1

「這是一個很好的解決方案嗎?」 - 什麼問題? –

回答

1

問:這些東西是一種很好的做法,設計明智嗎?

A.這樣做本身並沒有什麼壞處,它取決於要求。一般來說,如果你想確保構造函數不會拋出(這可能是你的意圖),這是很好的,並且如果你分配的數據對於對象的操作不是關鍵的,那麼它就是有意義的。在大多數情況下,如果構造函數中出現故障,最好拋出一個異常。請注意,如果你使用這個,你在訪問ptr []時也需要檢查NULL是否爲NULL。

問:無法按照預期方式創建的對象會發生什麼情況? 它會像「殭屍」一樣「活着」嗎?還是會被摧毀?

答:這可以通過兩種方式發生: 1.未能爲對象A本身分配內存。在這種情況下,它將取決於用於分配內存的方法。如果它的「新」,那麼它會默認拋出一個異常。 2.未能在分配中爲整數數組分配內存。在這種情況下,你會發現異常。在catch塊中,在這種情況下,使用destroy()重新分配ptr是不必要的,因爲try塊將失敗的唯一方式是不能爲n個整數數組分配內存。 A的構造函數會隱藏這個失敗,爲對象A分配的內存將保持原樣。

問:在矩陣方案中,矩陣分配多個新語句時該做什麼?

答:你的意思是如果你在for循環/多個新語句中爲ptr分配內存會發生什麼?如果是這樣,除非在這種情況下,已分配給ptr []的任何內存將保持原樣並且您需要catch塊中的destroy()調用以取消分配分配給ptr []的所有內存,否則行爲將會相同。注意在銷燬你將再次需要分別檢查NULL和釋放每個數組元素。

0

不,這些東西是一個壞主意。

根本問題是可組合性。像每個OO語言一樣,C++允許用戶定義的類型。這些類型可以包含不同類型的成員。 C++定義瞭如何創建和銷燬這些組合類型的規則。

C++規則是在寫出例外的情況下編寫的。他們是而不是寫在殭屍對象的腦海。創建成員時的例外會被傳播,並且其兄弟會被正確銷燬。成員的殭屍狀態是而不是繁殖,並且兄弟姐妹很難清理(如果有的話)。

現在你可能會認爲,不是依賴C++規則,而是可以引入一個公司方面的編碼標準,即複合對象應該有一個檢查所有成員的方法bool isZombie() const。但是C++有模板容器。 std::vector<YourClass>確實不是有一個isZombie()方法; std::vector<>不符合貴公司的編碼標準。但是,std::vector<T>確實T::T()宣傳例外。當它發生時,它不會破壞內部狀態。甚至沒有通過vector.resize()的一半。