I am working in c++ with structs and dynamic allocation,and i need to make function that automatically increases the size of array:
structType * array=new structType[max];
and i can't use `vectors'. Does anybody knows how to do this?
Following my comment, here's the implementation:
void resizeArray(structType*& oldArray, size_t oldSize, size_t newSize) {
structType* newArray = new structType[newSize];
for (size_t i = 0; i < std::min(oldSize, newSize); ++i)
newArray[i] = oldArray[i];
delete[] oldArray;
oldArray = newArray;
}
structType* array = new structType[max];
resizeArray(array, max, max + 10);
Note that the code above is not exception safe: if newArray[i] = oldArray[i]; throws then you will leak memory. But I believe this is enough to get you started.
Related
During the expansion of a dynamically allocated array, I find myself writing this :
void HPQueue::expandCapacity() {
char **prevArray = array;
capacity *= 2;
array = new char*[static_cast<size_t>(capacity)];
for (int i = 0; i < capacity; i++) {
array[i] = new char;
}
for (size_t i = 0; i < count; i++) {
array[i] = prevArray[i];
LINE XX: delete prevArray[i]; <----------- This line seems to be the problem, Since it also deletes array[i]
}
delete[] prevArray;
}
But this line is necessary if initially the constructor looks something like this:
HPQueue::HPQueue::() {
capacity = INITIAL_CAPACITY;
array = new char*[static_cast<size_t>(logSize)];
for (int i = 0; i < logSize; i++) {
array[i] = new char;
}
count = 0;
}
Note :
/* instances variables */
char **array;
size_t count;
Is this LINE XX: not necessary ?
No, you shouldn't be calling new char for the first count elements of array. You should be copying from the first count elements of prevArray.
You don't need to call new char at all. If you use nullptr instead, you can still safely delete[] array[i] when you remove an element.
But you shouldn't be doing this. In order of preference:
Use std::vector<std::string> array, it does all this for you.
Use std::unique_ptr<std::unique_ptr<char[]>[]> array; std::size_t capacity; and reassign with array = std::make_unique<std::unique_ptr<char[]>[]>(capacity); and move with std::move(prevArray.get(), prevArray.get() + count, array.get());
Use char **array; std::size_t capacity;, reassign with array = new char*[capacity]; and move with std::copy_n(prevArray, count, array);
So if you are required to go with the last one, you get
HPQueue::HPQueue()
: capacity(INITIAL_CAPACITY),
array(new char*[INITIAL_CAPACITY]),
count(0)
{
std::fill_n(array, capacity, nullptr);
}
void HPQueue::expandCapacity() {
char **prevArray = array;
capacity *= 2;
array = new char*[capacity];
auto pos = std::copy_n(prevArray, count, array);
std::fill_n(pos, capacity - count, nullptr);
delete[] prevArray;
}
I've been tasked with implementing a stack using arrays However, when I run the program it says _BLOCK_TYPE_IS_VALID(pHead -> nBlockUse). The debugger directed me to the delete statement in the resize function, but I'm unsure how to fix the problem.
Note: I'm trying to do so without using vectors.
void resize(){
Type* temp = new Type[asz + 2]; // store old values
for (int i = 0; i < asz; ++i){ temp[i] = arr[i]; }
delete[asz] arr; // delete old array
arr = temp; // keep new larger arr
delete[] temp;
asz =+2; // array size
}
Here's a couple of changes that may fix your problem. You don't initialise sz, your final for-loop was copying according to the new increased size, yet tempwas only the old size. You also don't appear to set the new sz anywhere. Could be any or all of these that cause a memory overwrite invalidating the debug blocks and causing the assertion you have seen.
void resize(Type& arg){
Type* temp = new Type[arg.sz]; // store old values
for (int i = 0; i < arg.sz; ++i){ temp[i] = arg[i]; }
int oldSz = arg.sz, newSz=arg.sz + 2;
delete[] arg; // delete old array
arg = new Type[newSz]; // create new larger arr
arg.sz = newSz;
for (int i = 0; i < oldSz; ++i){ arg[i] = temp[i]; } //copy back
delete[] temp;
}
The following snippet of code is my attempt to increase the size of an array by a factor of two. I am having several problems with it. Most importantly, should I be calling delete on my original array?
void enlarge(int *array, int* dbl int size) {
for (int i = 0; i < size; i++)
dbl[i] = array[i];
delete array;
array = dbl;
}
You have a few problems:
Modifying array only modifies the local copy of the pointer. You need to take a reference-to-pointer if you want the modification to be observed by the calling code.
You need to use delete[] when deleting things allocated with new[].
You attempt to copy too many items, and in so doing you overrun the original array.
void enlarge(int *& array, int size) {
// ^
// Use a reference to a pointer.
int *dbl = new int[size*2];
for (int i = 0; i < size; i++) {
// ^
// Iterate up to size, not size*2.
dbl[i] = array[i];
}
delete[] array;
// ^
// Use delete[], not delete.
array = dbl;
}
However, I would strongly suggest using std::vector<int> instead; it will automatically resize as necessary and this is completely transparent to you.
keyword double cannot be used as variable name, and previous array must be deleted before new allocation get assigned to same pointer, and loop should copy size no of items from prev array (not 2 * size)
void enlarge(int **array, int size) {
int *d = new int[size*2];
for (int i = 0; i < size; i++)
d[i] = *array[i];
delete [] *array;
*array = d;
}
if previous array was int *arr, and size is the currentsize of the array arr, call should be as: enlarge(&arr, size)
I have made a function for expanding array, and this function is inside a class.
Because this function creates new_arr and copies all the numbers of array into the new_arr and at the end sets pointer of array with new_arr, I wold like to know how to delete numbers in array becuse I dont need it any more
void Array::bigger() {
int new_size = size * 2;
int *new_arr = new int[new_size];
for (int f1=0; f1<last; f1++) {
new_arr[f1] = array[f1];
}
this->size = new_size;
array = new_arr;
}
Thanks
Assuming this is an exercise, then delete the array before re-assigning to the new one:
delete [] array;
array = new_arr;
In real code, use an std::vector<int> instead of the dynamically allocated array.
free memory before lose pointer to it:
void Array::bigger() {
int new_size = size * 2;
int *new_arr = new int[new_size];
for (int f1=0; f1<last; f1++) {
new_arr[f1] = array[f1];
}
this->size = new_size;
delete[] array; //free memory
array = new_arr;
}
So i'm trying to avoid using vectors to do this, i know it would make it easier, but i'm trying to better my understanding of pointers and arrays. So is there a way to expand and shift an array without using the vectors? Here is what i have so far:
int *expand(int *&arr, int size)
{
int *newArray;
size = size * 2;
newArray = new int[size * 2];
for (int index = 0; index < size; index++)
newArray[index] = arr[index];
return newArray;
}
The simplest way to do what you want would be the standard library function realloc.
http://www.cplusplus.com/reference/clibrary/cstdlib/realloc/
int* new_array = (int*) realloc (old_array, new_size * sizeof(int));
Note the *sizeof(int). That's important :)
realloc makes sure the contents of *old_array* can be found in *new_array*(it's either the same pointer, or the contents are copied). See the link for details.
In c++, try to avoid raw pointers. But since this is an exercise, this is a c++ way :
int *expand(int *&arr, int size)
{
int *newArray = new int[2*size];
std::copy( &arr[0],&arr[size], &newArray[0] );
// delete [] arr; // need to delete?
return newArray;
}
To do in place :
void expand(int *&arr, int size)
{
int *newArray = new int[2*size];
std::copy( &arr[0],&arr[size], &newArray[0] );
delete [] arr;
arr = newArray;
}
To do it manually, you need to copy the old data with the size of the original array, right now you're walking off the end of the original array.
Try this:
int *expand(int *&arr, int size)
{
int *newArray;
newArray = new int[size * 2];
for (int index = 0; index < size; index++)
newArray[index] = arr[index];
return newArray;
}
You're allocating twice as much memory as you need.
You're not deleting the old array.
You're not assigning the new pointer to arr - passing it as reference indicates that's what you intended - or that you intended to delete[] arr and assign 0 to it.
See this link for a method that uses memcpy instead of looping through individual items.
int *expand(int *&arr, int size)
{
size_t newSize = size * 2;
int* newArr = new int[newSize];
memcpy( newArr, arr, size * sizeof(int) );
size = newSize;
delete [] arr;
arr = newArr;
}
Since you aren't changing the value of arr inside the function, there's no need to pass the address by reference. If you did mean to change the value, you need to add a new line of code before the return newArray:
arr = newArray;
If the typical calling pattern is
arr = expand(arr, arr_size);
then you'll also need to watch out for options that ignore aliasing. And you'll have to make assumptions within expand that size is always doubled, and keep track of that yourself outside of it.
Also, your code has a terrible bug. size is doubled, and then used as the array limit for the source array. Then it leaks the memory that was previously allocated for arr. This is a good reason why people use std::vector. :-) Most of the bugs are out of that library, by now.
void expand_in_place(int *&arr, int& size)
{
const new_size = size * 2;
int *new_array = new int[new_size];
for (int index = 0; index < size; index++)
new_array[index] = arr[index];
delete[] arr;
arr = newArray;
size = new_size;
}
If you were using malloc and free instead of new [] and delete [], you could use realloc.