Delete a dynamic array but keep a pointer - c++

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;
}

Related

Is this extra step necessary when freeing dynamically allocated memory

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;
}

Doubling the Size of a C++ Array

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)

How do I make function that needs to do this?

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.

Copying from One Dynamically Allocated Array to Another C++

This seems like it should have a super easy solution, but I just can't figure it out. I am simply creating a resized array and trying to copy all the original values over, and then finally deleting the old array to free the memory.
void ResizeArray(int *orig, int size) {
int *resized = new int[size * 2];
for (int i = 0; i < size; i ++)
resized[i] = orig[i];
delete [] orig;
orig = resized;
}
What seems to be happening here is that resized[i] = orig[i] is copying values by reference rather than value, as printing orig after it gets resized returns a bunch of junk values unless I comment out delete [] orig. How can I make a deep copy from orig to resized, or is there some other problem that I am facing? I do not want to use std::vector.
Remember, parameters in C++ are passed by value. You are assigning resized to a copy of the pointer that was passed to you, the pointer outside the function remains the same.
You should either use a double indirection (or a "double pointer", i.e. a pointer to a pointer to int):
void ResizeArray(int **orig, int size) {
int *resized = new int[size * 2];
for (int i = 0; i < size; i ++)
resized[i] = (*orig)[i];
delete [] *orig;
*orig = resized;
}
or a reference to the pointer:
void ResizeArray(int *&orig, int size) {
int *resized = new int[size * 2];
for (int i = 0; i < size; i ++)
resized[i] = orig[i];
delete [] orig;
orig = resized;
}
By the way, for array sizes you should use the type std::size_t from <cstddef> - it is guaranteed to hold the size for any object and makes clear that we are dealing with the size of an object.
I highly suggest replacing the arrays with std::vector<int>. This data structure will resize as needed and the resizing has already been tested.
orig must be a pointer to a pointer to assign it to resized:
int **orig;
*orig = resized;

array manipulation

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.