1

I have a dynamic array as a member of my class. I'm trying to find an efficient way to resize it and keep all of the information in it. I know that vectors would work well for this but I want to do this with a dynamic array instead.

My class has a dynamic array of type unsigned _int8 called data.

Is the following acceptable?

unsigned _int8 * temp = data;
data = new unsigned _int8[NewSize]();

if(OldSize >= NewSize)
{
    for(int i = 0; i < NewSize; i++)
        data[i] = temp[i];
}
else
{
    for(int i = 0; i < OldSize; i++)
        data[i] = temp[i];
}

delete [] temp;

Or should I do this a different way? Any suggestions?

Edit

Fixed an error in my example and changed char to unsigned _int8.

Edit 2

I will not be reallocating often, if at all. I want the functionality to be there to avoid having to write the code to create a new object and copy everything over if it's needed.

The class I am writing is for creating and saving Bitmap (.bmp) images. The array simply holds the file bytes. The image size will (should) be known when I create the object.

Hill
  • 463
  • 3
  • 15
  • 6
    It looks like you are trying to re-implement `std::vector`. Just use `std::vector`. – juanchopanza May 10 '14 at 22:32
  • On a side note... `std::copy` – Ed S. May 10 '14 at 22:34
  • you are missing an `; ++i` in your second loop ;) – Mahrgell May 10 '14 at 22:34
  • 1
    If you really do not want to use std::vector or equivalent then perhaps you could drop back to C, especially given that this is a simple array of char. Use malloc() for the original char array, and then realloc() it when you need to resize it. – jarmod May 10 '14 at 22:36

3 Answers3

1

Since the array is using a POD (plain old data) type, you can replace the loops with memcpy() instead:

unsigned _int8 *temp = new unsigned _int8[NewSize];

if (OldSize >= NewSize)
    memcpy(temp, data, NewSize * sizeof(unsigned _int8));
else
{
    memcpy(temp, data, OldSize);
    memset(&temp[OldSize], 0, (NewSize-OldSize) * sizeof(unsigned _int8));
}

delete[] data;
data = temp;

Or at least use std::copy() (for POD types, std::copy() is like memcpy(), but for non-POD types it uses loops so object assignment semantics are preserved):

unsigned _int8 *temp = new unsigned _int8[NewSize];

if (OldSize >= NewSize)
    std::copy(data, &data[NewSize], temp);
else
{
    std::copy(data, &data[OldSize], temp);
    std::memset(&temp[OldSize], 0, (NewSize-OldSize) * sizeof(unsigned _int8));
}

delete[] data;
data = temp;

That being said, you really should use std::vector<unsigned _int8> instead. It handles these details for you. This type of array management is what you have to use in C, but really should not use in C++ if you can avoid it, use native C++ functionality instead.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • The array is actually unsigned _int8. Does this change anything? – Hill May 10 '14 at 22:40
  • No, it does not. Everything I said applies to that type as well, just replace `char` with `uint8` as needed. – Remy Lebeau May 10 '14 at 22:41
  • I don't know if vectors are going to have any functionality I need aside from this. I want to avoid adding anything I don't need. Besides, this a learning experience for me. The more I rely on libraries, the less I'm going to learn about C++. Thanks for the help. – Hill May 10 '14 at 22:49
  • This exercise is teaching you C, not C++. If you really want to learn C++, then learn C++, including what C++ offers that C does not (like the STL library, which is a native part of C++). – Remy Lebeau May 10 '14 at 22:51
  • Would you personally always use a vector in place of a dynamic array? Just curious. I've never used C++ in a professional environment so I don't know what is standard. – Hill May 10 '14 at 22:59
  • `The more I rely on libraries, the less I'm going to learn about C++` What is your goal? Is it to develop a real usable application, or is it to fiddle around with implementing dynamic arrays? Using the STL and other libraries frees you from thinking about low-level details, and instead gets you thinking about the overall structure of your program and how to design it properly. Program design and using the tools properly still takes skill, so saying "you will learn less C++" is a misnomer. – PaulMcKenzie May 10 '14 at 23:45
  • @user3624257: yes, I do use `std::vector` (and other STL containers, like `std::list` and `std::map`) in production code. – Remy Lebeau May 11 '14 at 02:32
0

By doing it this way, every time a new element is added to the array, it must be resized. And the resize operation is Θ(n), so the insert operation also becomes Θ(n).

The common procedure is to duplicate (or triplicate, etc) the array size every time it has to be resized, with this, the resize operation is still Θ(n), but the amortized insertion cost is Θ(1).

Also, usually the capacity is separated from the size, because the capacity is an implementation detail, while the size is part of the interface of the array.

And you may want to verify, when elements are removed, if the capacity is too big, and if so, decrease it, otherwise, once it gets big, that space will never be released.

You can see more about it here: http://en.wikipedia.org/wiki/Dynamic_array

  • I'm sorry, I should have provided more information in my question. Everything you said is true and good advice, but for my particular problem Remy Lebeau has a better answer I think. – Hill May 10 '14 at 22:53
0

The problem with this approach is that you resize to just the size needed. This would mean that when you insert a new element the time needed to do it varies a lot.

So for example if you keep doing a "push_back" like operation then you would reallocate all the time.

An alternative idea is to allocate extra size to avoid frequent reallocations that cost a lot regarding performance

Vector for example allocate extra size to have an amortisized redimensionning constant.

Here is a link that exaplains it in detail

Vector in the stl use this method to be more effiicient.

Amortized analysis of std::vector insertion

Community
  • 1
  • 1
Gabriel
  • 3,564
  • 1
  • 27
  • 49
  • I'm sorry, I should have provided more information in my question. Everything you said is true and good advice, but for my particular problem Remy Lebeau has a better answer I think. Also, vectors are great and I've actually used them several times before. I don't think they have any functionality I need aside from this though and I want to avoid adding anything to my project I don't need. – Hill May 10 '14 at 22:54
  • ok sure, so you should also vote for his answer to give him extra points. Sinply click on the up arriw next to the 0 you see close to his answer – Gabriel May 10 '14 at 23:06