2010-01-17 74 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] ...