NGix
NGix

Reputation: 2662

How to resize array of struct elements

I'm writing a program, where I have one class, inside that class ( or outside, hope it doesn't matter ) I have struct. In that class I need to make an array of struct elements ( I know I can use vector e.g. but in program it is only permitted to use simple dynamic arrays ).

I declare an array as T * arr[SIZE], where T is my struct. The only problem is I don't know exact size of array and need to increase it size if necessary. So I wrote function to resize it:

if( some cond ){
    T * tmpArr[newSIZE];
    memcpy( tmp, db, newSIZE*sizeof(T));
    delete [] arr;
    arr = tmpArr;
}

But I'm getting a error that MyClass::T[....] is incompatible with MyClass::T*[SIZE] which responds to my arr = tmpArr expression I guess.

Can you tell me what I'm doing wrong? And how is better to declare T * arr[size] or T * arr = new T[size] and how do I resize ( and free memory from old one ) array in that case?

UPDATE:

Thanks for answers, I did accordingly in my program:

    T * tmp = new T[newSIZE];
    memcpy( tmp, db, newSIZE*sizeof(T) );
    delete [] db;
    db = tmp;

And now I'm getting weird things, after deleting db and assigning db to tmp I try to print all data contained in db ( or tmp ), that weird thing I get:

   Smith2 Michigan ave▒ ACME, Ltd. One ACME roa▒
   Smit▒ Michigan ave` ACME, Ltd. One ACME roa "

   One ACME road#@"▒▒▒▒Michigan ave`▒▒▒▒Smit▒"

   ▒▒ ▒8 Ltd.#Michigan avenuemith4▒aF▒

If I print same data before deleting and assigning, I'll get normal text I want. And after in program ( as I didn't have before and maybe that's problem with my code, I get Segmentation fault ). By the way, I'm using struct of std::string and cygwin in my windows. Do you have any idea what's the problem here?

Upvotes: 0

Views: 5561

Answers (5)

didierc
didierc

Reputation: 14730

I will suppose that you actually want to store pointers to T. You need to:

  • add a missing *, since you are allocating an array of pointers to T,
  • remove the size for tmpArr and arr

So:

// arr definition
 T **arr;;

// arr resizing code
if( some cond ){
    T **tmpArr;
    memcpy( tmp, db, newSIZE*sizeof(T *));
    delete [] arr;
    arr = tmpArr;
}

Your array stores pointers to T, not T, and tmpArr size isn't known at compile time, so you cannot specify it in its type.

Caveat: if the new size is smaller than the current one, you will lose the pointers at the end of the array. You should add a test on that, and delete these extra T (if your container owns them), or simply throw an exception, since the code is only supposed to increase the size of the array.

Upvotes: 0

LihO
LihO

Reputation: 42083

T* tmpArr[newSIZE]; declares a variable-length array of pointers to T. Note that variable-length arrays are not part of standard C++ (they are part of C99, but in C++ available only as an extension of GCC... this code is thus uncompileable with different compilers).

Perfectly reasonable solution would be to use std::vector, but since you yourself wrote that you are not allowed to use it, then here's what you could do.

  1. change T* tmpArr[newSIZE]; to T* arr = new T[size];
  2. now to resize this array:
    1. allocate new array: T* newArr = new T[newSize]
    2. copy elements from old array: memcpy(newArr, arr, size * sizeof(T))
    3. deallocate the old array using delete[]: delete[] arr
    4. since delete doesn't change the pointer itself, you have invalid (dangling) pointer after step 3, so assign the pointer to the first element of new array to old one: arr = newArr
  3. keep track of the size of the array that you are working with

Note that T* arr = new T[size] allocates the memory big enough to hold size objects of type T and constructs these object by using the default constructor of T. The address of the first element is then assigned to arr making it point to the continuous memory block, where these elements reside.

Upvotes: 4

Darokthar
Darokthar

Reputation: 1113

I guess you are trying to delete an array you created like this:

T array[size];

But you should not call delete on this. This array is deleted, when it goes out of scope. If you want to create an array and free it afterwards you have to use the new operator when declaring the array. If you want to free it use delete.

But anyway you might want to use std::vector instead of trying to do it by yourself. If you are interested in learning about this stuff there was/is a video series on channel9 from Microsoft by Stephen T. Lavavej here:

http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Standard-Template-Library-STL-/C9-Lectures-Introduction-to-STL-with-Stephan-T-Lavavej which is a real gem.

Upvotes: 1

The simple solution is not to reinvent the square wheel, but use the already round and polished std::vector<Type> template in the standard library.

Upvotes: 0

Joseph Mansfield
Joseph Mansfield

Reputation: 110658

T arr[N];

A declaration of this form gives you an array of size N with automatic storage duration. This is fixed. You can't change the size of this array. The size N has to be a compile-time constant.

T* arr = new T[N];

This declaration defines a T* with automatic storage duration. However, it also creates an array of size N with dynamic storage duration. Here, the size N doesn't need to be a compile-time constant.

However, this doesn't help you. You still can't resize a dynamic array. You would have to do delete[] arr to destroy the old array and then do new T[NewSize] and somehow copy the data across.

This is sure to get messy, and in fact it has. In your code, you're mixing up the two different types of allocation. You're attempting to do delete[] arr even though arr does not have dynamic storage duration. You simply can't do this. You also can't assign one array to another, as in arr = tmpArr;.

Instead, the C++ standard library provides a number of types called containers. These make it very easy to have dynamically resizeable sequences of elements. For example, you would be much better off using a std::vector<T>.

std::vector<T> arr;

A std::vector begins with no elements. You can add elements simply by doing arr.push_back(value). You can also resize the vector in one go very easily by doing arr.resize(newSize).

Upvotes: 3

Related Questions