Reputation: 2662
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
Reputation: 14730
I will suppose that you actually want to store pointers to T
. You need to:
*
, since you are allocating an array of pointers to T
,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
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.
T* tmpArr[newSIZE];
to T* arr = new T[size];
T* newArr = new T[newSize]
memcpy(newArr, arr, size * sizeof(T))
delete[]
: delete[] arr
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
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
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
Reputation: 208353
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
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