Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array as private member of class

Tags:

c++

arrays

I am trying to create a class which has a private member that is an array. I do not know the size of the array and will not until the value is passed into the constructor. What is the best way to go about defining the class constructor as well as the definition in the .h file to allow for this variable size of the array?

like image 692
finiteloop Avatar asked Jan 17 '10 22:01

finiteloop


1 Answers

If you want a "real" C-style array, you have to add a pointer private member to your class, and allocate dynamically the memory for it in the constructor (with new). Obviously you must not forget to free it in the destructor.

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;
    }
};

To make this work easier, you may consider to use a smart pointer (for example, a boost::scoped_array in C++03, or plain std::unique_ptr in C++11), that you may initialize using the initializer list before the constructor or simply in the constructor.

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
};

Both these solutions produce noncopyable objects (you didn't specify if they had to be copyable and their copy semantic); if the class don't have to be copied (which happens most of times), these both are ok, and the compiler will generate an error if you try to copy/assign one class to another, in the first case because the default copy constructor has been overloaded with a private one (or plain deleted in C++11), in the second case because boost::scoped_array and std::unique_ptr are noncopyable.

If, instead, you want to have copyable objects, then you must decide if you want to create a copy that shares the array (so, just a pointer copy) or if you want to create a new, separate array for the other object.

In the first case, you must be very careful before freeing the allocated memory, since other objects may be using it; a reference-counter is the most common solution. You can be helped in this by boost::shared_array (or std::shared_ptr in C++11), which does all the tracking work automatically for you.

If instead you want to do a "deep copy", you'll have to allocate the new memory and copy all the objects of the source array to the target array. This is not completely trivial to do correctly, and is usually accomplished through the "copy and swap idiom".

Still, the simplest solution is to use a std::vector as a private member: it would handle all the allocation/deallocation stuff by itself, constructing/destroying itself correctly when the object of your class is constructed/destructed. Moreover, it implements the deep-copy semantic out of the box. If you need to make your callers access the vector read-only, then, you could write a getter that returns a const_iterator or a const reference to the vector object.

like image 189
Matteo Italia Avatar answered Sep 22 '22 17:09

Matteo Italia