2010-01-17 111 views
13

我想創建一個具有私有成員的類,它是一個數組。我不知道數組的大小,直到值傳遞給構造函數。定義類構造函數以及.h文件中的定義以允許此數組的可變大小的最佳方法是什麼?數組作爲類的私有成員

回答

10

如果你想要一個「真正的」C風格的數組,你必須向你的類添加一個指針私有成員,並在構造函數中動態分配它的內存(與)。顯然你不能忘記在析構函數中釋放它。

class YourClass 
{ 
    private: 
    int * array; 
    size_t size; 

    // Private copy constructor operator to block copying of the object, see later 
    // C++03: 
    YourClass(const YourClass &); // no definition 
    // C++11: 
    YourClass(const YourClass&) = delete; 

    public: 
    YourClass(size_t Size) : array(new int[Size]), size(Size) 
    { 
     // do extra init stuff here 
    }; 

    ~YourClass() 
    { 
     delete [] array; 
    } 
}; 

爲了使這項工作更容易,你可以考慮(在C++ 03或C++ 11平std::unique_ptr例如boost::scoped_array)使用智能指針,你可以使用初始化初始化在構造函數之前列出或僅在構造函數中列出。

class YourClass 
{ 
    private: 
    boost::scoped_array<int> array; // or in C++11 std::unique_ptr<int[]> array; 
    size_t size; 
    public: 
    YourClass(size_t Size) : array(new int[Size]), size(Size) 
    { 
     // do extra init stuff here 
    } 

    // No need for a destructor, the scoped_array does the magic 
}; 

這兩種解決方案產生不可複製的對象(如果他們不得不可拷貝和複製他們的語義沒有指定);如果不需要複製類(這會發生大部分時間),那麼這兩者都可以,如果您嘗試將一個類複製/分配給另一個類,則編譯器將生成錯誤,在第一種情況下,因爲缺省副本在第二種情況下,構造函數已被重載(或在C++ 11中被簡單刪除),因爲boost::scoped_arraystd::unique_ptr是不可複製的。

如果您想擁有可複製的對象,那麼您必須決定是否要創建共享數組的副本(所以,只是一個指針副本),或者如果您想創建一個新的獨立數組另一個對象。

在第一種情況下,釋放分配的內存之前必須非常小心,因爲其他對象可能正在使用它;參考計數器是最常見的解決方案。您可以通過boost::shared_array(或C++ 11中的std::shared_ptr)幫助您完成所有跟蹤工作。

如果您想要執行「深層複製」,則必須分配新內存並將源數組的所有對象複製到目標數組。這不是完全正確的微不足道的,通常通過"copy and swap idiom"完成。

儘管如此,最簡單的解決方案是使用一個std::vector作爲私有成員:它會自己處理所有的分配/解除分配的東西,當你的類的對象被構​​造/破壞時,正確地構造/銷燬它自己。此外,它實現了深入複製語義。如果您需要讓您的調用者以只讀方式訪問向量,那麼您可以編寫一個吸氣器,該吸氣器返回const_iteratorconstvector對象的引用。

+1

對於數組,您需要確保使用' scoped_array',而不是'scoped_ptr'。 – 2010-01-17 23:01:17

+0

更正,謝謝。我總是得到delete []權利,但有時我忘記了智能指針的陣列版本。 – 2010-01-17 23:04:21

+0

唯一的竅門是如果YourClass將被複制,因爲scoped_ *在boost中是不可複製的。無論如何,這在問題中沒有說明,所以無論如何+1。 – Skurmedel 2010-01-17 23:04:31

2

使用std :: vector是最好的選擇。 如果您需要將它傳遞給一個指向數組的指針(如GSL經常這樣做),那麼您仍然可以通過&vec[0] ...