I've searched through many topics here, but they didn't seem to answer me exactly.
I'm trying to do some dynamic reallocation od arrays in C++. I can't use anything from STL libraries as I need to use this in homework where STL (vectors,...) is explicitly forbidden.
So far, I've tried to elaborate with code like this:
int * items = new int[3]; //my original array I'm about to resize
int * temp = new int[10];
for (int i = 0; i < 3; i++) temp[i] = items[i];
delete [] items; //is this necessary to delete?
items = new int [10];
for (int i = 0; i < 10; i++) items[i] = temp[i];
delete [] temp;
This seem to work, but what bothers me is the excessive number of iterations. Can't this be done anyhow smarter? Obviously, I'm working with much larger arrays than this. Unfortunately, I have to work with arrays though.
edit: When I try to do items = temp; instead of
for (int i = 0; i < 10; i++) items[i] = temp[i]; and try to std::cout all my elements, I end up with losing first two elements, but valgrind prints them correctly.
Yes, the first delete[] is necessary. Without it, you'd be leaking memory.
As to the code that comes after that first delete[], all of it can be replaced with:
items = temp;
This would make items point to the ten-element array you've just populated:
int * items = new int[3]; //my original array I'm about to resize
int * temp = new int[10];
for (int i = 0; i < 3; i++) temp[i] = items[i];
delete [] items; //delete the original array before overwriting the pointer
items = temp;
Finally, don't forget to delete[] items; when you are done with the array.
The containers of the STL were made to ease work like this. It is tedious, but there is not much of a choice, when you need to use C-arrays.
The deletion of
delete [] items;
is necessary, as when you abandon the reference to the array, which you would do with assigning a new reference in
items = new int [10];
will cause a memory leak, so this is necessary.
Related
int *array[10];
for(int i = 0; i < 10; i++)
array[i] = new int[10];
//...
void passFunc(int *a[10]) //array containing pointers
{
//...
}
passFunc(array);
Im trying to figure out how to declare and delete this version of a 2D array. I started using int ** array, but in order to make one section of code easier, I need to switch to *[]. Can anyone help me out?
I have tried compiling my actual code (the above code is just an example), which looks like this:
int* filedata[LENGTH] = new int*[LENGTH]; //ERROR: array must be initialized with brace- enclosed identifiers.
EDIT:
Thanks!
Something like that
int** array = new int*[sizeX];
for(int i = 0; i < sizeX; ++i)
array[i] = new int[sizeY];
To delete
for(int i = 0; i < sizeX; ++i)
delete [] array[i];
delete [] array;
If I have understood correctly what you want then the allocation and deallocation will look as
int ** filedata = new int * [LENGTH];
for ( int i = 0; i < LENGTH; i++ ) filedata[i] = new int [LENGTH];
//...
for ( int i = 0; i < LENGTH; i++ ) delete [] filedata[i];
delete [] filedata;
Alternate version to the ones given:
int** array = new int*[sizeX];
int *pool = new int[sizeX * sizeY];
for(int i = 0; i < sizeX; ++i, pool += sizeY)
array[i] = pool;
To delete:
delete [] array[0];
delete [] array;
The advantage of using this is:
Only two calls to new[] and delete[] are required, regardless of the number of columns. In the previous answer, the number of calls to new and delete depend on the number of columns. This reduces fragmentation, and also will probably give you a speed increase if the number of columns is very large.
The data is contiguous. You can access any element in the 2d array from any other element using a simple offset.
The disadvantage is that the number of columns for each row needs to be the same, otherwise it becomes very difficult to maintain.
I get very frustrating error in following piece of code. Thats my array.
int **tab2 = new int*[3];
I allocate this like it.
for(i = 0; i < 10; i++) {
tab2[i] = new int[3];
tab2[i][0] = 40;
tab2[i][1] = 10;
tab2[i][2] = 100;
}
Then after using it i want to destroy it.
for(i = 0; i < 10; i++) {
delete [] tab2[i];
}
delete [] tab2;
And this causes core dump every single time. I tried many different ways to destroy it and every time get this error. What im making wrong here ?
This
int **tab2 = new int*[3];
does not do what you think it does.
You want an array that will contain TEN (10) pointers, each to an array of THREE ints.
new int*[3] is an array that contain THREE pointers.
What you want is this (live at coliru):
#include <iostream>
int main() {
int **tab2 = new int*[10];
for(int i = 0; i < 10; i++) {
tab2[i] = new int[3];
tab2[i][0] = 40;
tab2[i][1] = 10;
tab2[i][2] = 100;
}
for(int i = 0; i < 10; i++) {
delete [] tab2[i];
}
delete [] tab2;
}
With
int **tab2 = new int*[3];
you allocate an array of pointers of size 3. But than with
for(i = 0; i < 10; i++) {
tab2[i] = new int[3];
//...
}
you access it with up to index 9. That will surely go wrong.
The deletion process looks fine to me. To fix it, you should allocate an array of pointers with size 10instead of 3, e.g.
int **tab2 = new int*[10];
Looks like what you're trying to do is to create an N by M array, where N is known at runtime and M is fixed (in this case, 3).
Why not just do this?
{
std::array<int, 3> defaults = {{ 40, 10, 100 }};
std::vector<std::array<int, 3>> thing(10, defaults);
}
The vector, thing is automatically deallocated when it goes out of scope, and its size can be set at runtime. You still access the structure in the same way:
thing[1][2] = 3
Manual memory management can be easily avoided by using standard containers and smart pointers. Doing so will keep you code cleaner, and have fewer opportunities for dangling pointers and memory leaks.
Okay, I'm writing a program that will perform different functions on an array. If necessary, the array will need to change capacity. The instructions are:
Create an new array.
Copy the contents from the old array to the new.
Delete the old array.
This part is understand, but what I don´t understand is how to keep a reference to the array that the functions will work with. This is my code for creating a new array and move over the elements.
int newSize = m_size*2;
double *tempArray= new double[newSize];
for(int i=0; i<m_size-1; i++)
{
tempArray[i] = arr[i];
}
delete []arr;
for(int i=0; i<m_size-1; i++)
{
arr[i] = tempArray[i];
}
delete []tempArray;
}
All the other methods use arr so I would like to reference back to that. A pointer won´t work since it only points to the first element. How can I use my arr variable to refer to an array?
In C and C++ dynamic arrays are usually represented by a pointer to the first element and the number of elements. So I'm assuming the following declarations:
double *arr;
int m_size;
If by any chance you have arr decleared as a real array double arr[..], then you cannot do delete []arr nor change its size!
Then your code should be along the lines of:
int newSize = 2*m_size;
double *tempArray= new double[newSize];
for(int i=0; i<m_size-1; i++)
{
tempArray[i] = arr[i];
}
delete []arr;
arr = tempArray;
m_size = newSize;
But now I wonder: why m_size-1 in the loop?
And also, you can just do:
memcpy(tempArray, arr, sizeof(*arr) * m_size)); //or m_size-1?
All this is nice if it is an exercise. For real code it almost always better to use std::vector<double> and the resize() member function.
You got undefined behaviour in your code.
delete []arr;
for(int i=0; i<m_size-1; i++)
{
arr[i] = tempArray[i];
}
You delete the memory arr was pointing to and then assign to the deleted memory inside the loop. Instead you should just write:
delete []arr;
arr = tempArray;
The whole code would be:
int newSize = m_size*2;
double *tempArray= new double[newSize];
for(int i=0; i<m_size-1; i++) // -1 might be wrong, look below for a comment on this line.
{
tempArray[i] = arr[i];
}
delete []arr;
arr = tempArray;
m_size = newSize // stolen from the others *cough* since I oversaw the need.
// note that I don't call delete on tempArray.
}
Also I don't know how you allocated your first array but if you made it calling new double[m_size] then you'd want to delete the -1 in the loop condition of the for loop since you're checking for i < m_size and not i <= m_size.
You need to allocate memory for ar after deallocating it.
int newSize = m_size*2;
double *tempArray= new double[newSize];
for(int i=0; i<m_size-1; i++)
{
tempArray[i] = arr[i];
}
delete []arr;
ar = new double[newSize];
for(int i=0; i<m_size-1; i++)
{
arr[i] = tempArray[i];
}
delete []tempArray;
delete []arr;
for(int i=0; i<m_size-1; i++)
{
arr[i] = tempArray[i];
}
Oops. Don't access after delete. And don't delete unless it was allocated with new.
You simply can't reallocate an array declared as
int arr[100]
or similar.
Based on the code you've given, what you're currently performing is:
Create a new array (tempArray)
Copy the contents of the old (arr) array to the new (temp) - (note - what happens if you make the new array smaller than the old?)
Delete the old array
Copy the new values back into the deleted remains of the old array (note - you deleted arr so you can't use it now!)
Delete the new array (so everything is gone)
Basically, you need to fix step 2, to handle sizes, and get rid of steps 4 and 5 entirely - you just need to re-assign arr instead:
arr = tempArray
You just have to declare the array arr and put the values in it. You can refer to the array through its pointer arr or each element with arr[element_id].
You have a couple of options here:
Take the C-style approach of just storing the pointer to the first element like you have, plus the length. From those two you can calculate anything you need.
Use std::vector. It holds an array, allows you to easily resize it with functions like emplace_back, and can tell you its length with the size function.
The second approach is certainly preferred. If you're in C++, you should usually be using std::vector instead of raw arrays, unless you're looking for a fixed-sized one. In that case use std::array.
You also get the added benefit of copying a vector being as simple as vector1 = vector2;.
My question arises from this answer.
In the comments he mentions that I should delete the allocated dynamic 2D array in the reverse order.
However I did not understand much why this should be done. Here is the code:
//intialising array
int size = 10000;
double **array = new double[size];
for(int i = 0; i < size; i++)
array[i] = new double[size];
//conventional de-initialise
for(int i = 0; i < size; i++)
delete[] array[i];
delete[] array;
//reverse de-initialise
for(int i = size - 1; size >= 0; i--)//notice reverse order here
delete[] array[i];
delete[] array;
So my question is, is there any significant difference between the 2 methods of de-allocating a 2D array?
In your example there's no difference - you create 100K pointers, and then allocate memory for each. It doesn't matter how you allocate/deallocate memory and assign it to pointers array.
However your question is about why reverse deallocation was in another post, and opposite to your example it matters - counter variable is reused to countdown from last allocated object down to 0, when new memory allocation failed. If deallocating other direction you'd need additional variable there:
try
{
array = new double*[size];
// Don't shadow counter here.
for(counter = 0; counter < size; counter++)
{
array[counter] = new double[size];
}
}
catch(std::bad_alloc)
{
// delete in reverse order to mimic other containers.
for(--counter; counter >= 0;--counter)
{
delete[] array[counter];
}
delete[] array;
I have a 2D array with size 4 (4 rows). To make the array size 2 (2 rows), can I use following? (for our hw assignment details are not specified and the code should be suitable with common c++ standarts)
I am removing second half of the array.
const int newSize = flightsArraySize/2;
for(int i = newSize-1; i < flightsArraySize-1; i++)
delete [] flights[i];
Or do I have to recreate flights array with size 2?
Supposing that you have created a 2D array using new like this:
int **arr = new int*[rows];
for(int i=0; i<rows; ++i)
arr[i] = new int[cols];
Then to resize it you'd have to do something like:
int newRows = rows/2;
// Create a new array for the right number of rows.
int **newArr = new int*[newRows];
// Copy the rows we're keeping across.
for(int i=0; i<newRows; ++i)
newArr[i] = arr[i];
// Delete the rows we no longer need.
for(int i=newRows; i<rows; ++i)
delete[] arr[i];
// Delete the old array.
delete[] arr;
// Replace the old array and row count with the new ones.
arr = newArr;
rows = newRows;
But seriously, this is all so much easier if you just use vector:
std::vector<std::vector<int>> v(rows);
for(int i=0; i<rows; ++i)
v[i].resize(cols);
v.resize(v.size()/2);
Well, it deallocates the memory on which pointed the second half of pointers. But the poiters themselves will stay, the array of pointers will not be shortened.
EDIT
Oh, sorry. It seems as a mistake. If you have code like this:
int **ptr = new int*[4];
for(int i = 0; i < 4; i++)
{
ptr[i] = new int[4];
}
Then when you type
delete[] ptr[3];
It will delete the whole array, so you can create new like this:
ptr[3] = new int[any_number];
Is this what you mean? Sorry, I read too fast...