0

I have a class, whereby one of its elements is of another class, but is an array

class B
{
public:
    B()             //default
    {
        element = new A [1]; count = 0;
    }

    A add(A place)
    {
        A* newArr;
        newArr = new A [count+1];

        newArr = element;
        newArr[count+1] = place;
        delete element;

        return newArr[count+1];
    }



protected:
    int count;
    A* element;
};

I am trying to use dynamic arrays, where I when adding the element, I make a new array dynamically, initilzed to the size of the old array plus 1, then copy the elements of the old array to the new array, and then delete the old array. But I am unsure of how to modify the array that's already within the class, if that makes sense (Basically what to return in my add method).

DebareDaDauntless
  • 471
  • 2
  • 7
  • 12

2 Answers2

2

In C++ there's no notion of resizing arrays once declared. Same goes for dynamic arrays, which can't be resized once allocated. You can, however, create a bigger sized array, copy all elements from the older array to the newer one and delete the old one. This is discouraged and would not be performant.

Using std::vector would allow you to add at will and will also keep track of its size, so you don't need count as part of the class.

class B
{
   // no need to allocate, do add when required i.e. in B::add
   B() : count(), elements() { }

   A add(A place)
   {
      // unnecessarily allocate space again
      A *new_elements = new A[count + 1];

      // do the expensive copy of all the elements
      std::copy(elements + 0, elements + count, new_elements);

      // put the new, last element in
      new_elements[count + 1] = place;

      // delete the old array and put the new one in the member pointer
      delete [] elements;
      elements = new_elements;

      // bunp the counter
      ++count;

      return place;    //redundant; since it was already passed in by the caller, there's no use in return the same back
   }

protected:
   size_t count;
   A *elements;
};

The above code perhaps does what you want but is highly discouraged. Use a vector; you code will simply become

class B
{
    // no need of a constructor since the default one given by the compiler will do, as vectors will get initialized properly by default

    void Add(A place)
    {
         elements.push_back(place);
         // if you need the count
         const size_t count = elements.size();
         // do stuff with count here
    }

    protected:
       std::vector<A> elements;
};
legends2k
  • 31,634
  • 25
  • 118
  • 222
  • Strictly speaking, this is correct. However, since C++ inherits the C standard library, you can resize memory using realloc: http://www.cplusplus.com/reference/cstdlib/realloc/ (just not memory that was allocated using `new`). – Zac Howland Oct 13 '13 at 03:34
  • @ZacHowland: I know, one can realloc but chances of it creating issues are high; if one had a pointer to some inner element, there's no guarentee that it'll be valid of the realloc. Moreover, meddling with low level constructs is needed only if no other solution is available. Otherwise using the standard facilities available will save a lot of time and effort. – legends2k Oct 13 '13 at 03:40
  • I don't disagree. I was just pointing out that it *can* be done ... whether it should be is an entirely different matter. – Zac Howland Oct 13 '13 at 03:41
  • Got it. Moreover, I wanted to give the OP a taste of what a reallocation would mean i.e. the expense of copying all elements from on location to another. Of course, using `realloc` shouldn't do this, since it'd be a `memcpy` under the hood. [Using realloc is risky](http://stackoverflow.com/a/9071767/183120). – legends2k Oct 13 '13 at 03:43
  • [How do you use calloc in C++?](http://stackoverflow.com/q/3482941/183120). You don't, use vector is the accepted answer :) – legends2k Oct 13 '13 at 03:51
  • Until you have to program for a platform that doesn't support the full language standard (e.g. embedded systems) ;) – Zac Howland Oct 13 '13 at 04:37
0

A more thorough example would be to more closely mimic std::vector:

template<typename T>
class B
{
private: // don't put data under a protected access!
    std::size_t _capacity;
    std::size_t _size;
    T* _elements;

public:
    B() : _capacity(0), _size(0), _elements(nullptr) {}

    // other methods

    void add(const T& t)
    {
        if (_size >= _capacity) // need to resize the array
        {
            _capacity++; // you can make this better by increasing by several at a time
            T* temp = new T[_capacity];
            std::copy(_elements, _elements + _size, temp);
            delete [] _elements;
            _elements = temp;
        }
        _elements[_size++] = t;
    }
};
Zac Howland
  • 15,777
  • 1
  • 26
  • 42