I have a triple pointer to an Object in C++ and I need to free the entire thing after use.
MyClass *** foobar = new MyClass **[10000];
How do I write the delete statement for this.
It depends on how you allocate the pointers-to-pointers. If you do:
int x;
int* p = &x;
int** pp = &p;
int*** ppp = &pp;
Then you don't have to delete anything.
On the other hand, if you do:
int* p = new int;
int** pp = &p;
int*** ppp = &pp;
Then you only have to delete p. For:
// i.e., allocate 1000 ints, return a pointer, and then get the address of that pointer
int** pp = &(new int[1000]);
// Oh, and get the address of the int**
int*** ppp = &pp;
You have to delete[] *pp (i.e., dereference pp to get the original pointer to the array of ints, and then delete[] the array).
How do you alloc it? Generally, if A is pointer to B, B is pointer to C and C is pointer to D (data), you need to free D, then C and B as the last one.
Anything you new[], you will have to delete[]. It's that simple.
If you do it at several levels, you will have to delete[] in the reverse order of the new[]'s.
If the only allocation that you have done is the one you show in the question, then you only need to do:
delete [] **foobar;
As that is the only memory that was actually acquired. If you have allocated memory to elements inside foobar, then you must clear them up in reverse order of creation.
Note that in most cases these types of structures can be simplified. For example, if the actual data to hold is a cube, you can allocate a single block of 1000*1000*1000 elements (that is a HUGE amount of them) and deallocate it with a single delete []. If you wrap the memory inside a class, then you can provide operator() that will map from three indices to the unique element in the sequential container. Take a look at the C++FAQ lite here.
3D memory allocation
int ***allocate3D(int ***mat, int k, int l, int m) {
mat = (int***) malloc( sizeof(int)*k*l*m );
for(int i=0;i<k;i++)
mat[i] = (int**) malloc ( sizeof(int)*l*m );
for(int i=0; i<k; i++) for(int j=0; j<l; j++)
mat[i][j] = (int*) malloc ( sizeof(int)*m );
return mat;
}
3D matrix deallocation:
void deAllocate3D(int ***mat, int k, int l, int m){
//Delete in reverse order of allocation
for(int i=0; i<k; i++) for(int j=0; j<l; j++) { free(mat[i][j]); mat[i][j] = NULL; }
for(int i=0; i<k; i++) { free(mat[i]); mat[i] = NULL; }
free(mat); mat = NULL;
}
Find the full source code here
Related
I'm trying to delete my 2D array, but I consistently get errors when I try to delete it, we have to work backwards so I delete the elements first, then the column array, then the row array. here is my code for the constructor in my class, MyMatrix:
private:
int m; //rows
int **ptr; //ptr to first dimension
int n; // columns
public:
MyMatrix() //constructor
{
m = 0;
n = 0;
ptr = new int*[m];
int *length_arr = new int[m];
for (int i = 0; i <= m-1; i++)
{
*(ptr+i) = new int[n];
*(length_arr+i) = n;
}
}
and my destructor looks like this:
for(int i = 0; i <= m-1; i++)
{
for (int j = 0; j <= n-1; j++)
{
delete ((*(ptr+i))+j);
}
delete[] *(ptr+i);
}
delete[] ptr;
the error I'm getting is:
assg7(2677,0x100de3d40) malloc: *** error for object 0x12d606804: pointer being freed was not allocated
I've wracked my brain for where I can fix this, for context, I'm doing an assignment with operator overloading. I specifically need a delete function to work properly for my = assignment overloading since I want to delete and again reallocate memory to equate two matrices, but the terminal is showing malloc errors and is thus not equating the matrices.
for additional info here is my = overloading code:
void operator = (const MyMatrix &obj)
{
if(n == obj.n && m == obj.m)
{
//for loop to equate elements in this-> to the elements of the passed object
}
else
{
for(int i = 0; i <= m-1; i++)
{
for (int j = 0; j <= n-1; j++)
{
delete ((*(ptr+i))+j);
}
delete[] *(ptr+i);
}
delete[] ptr;
// the code for assigning new memory according to the passed objects rows and colums goes here
//then for loop to equate elements in this-> to the elements of the passed object
}
}
thanks.
You have two "levels" of new, so three "levels" of delete can't be right.
Spell out your deletion loop, using indexing instead of pointer arithmetic:
First iteration:
delete ptr[0]+0;
delete ptr[0]+1;
...
delete ptr[0]+n-1;
delete [] ptr[0];
Second iteration:
delete ptr[1]+0;
delete ptr[1]+1;
...
delete ptr[1]+n-1;
delete [] ptr[1];
You're passing to delete a pointer to the first element of ptr[0], a pointer to the second element of ptr[0], a pointer to the third element of ptr[0], ...
But the things you allocated were ptr[0], ptr[1], ... ptr[m-1], not their individual elements.
Remove the innermost deletion loop.
(And don't mess around with pointer arithmetic when you can use indexing.)
I don't know how you would want to allocate memory space by m length if it is set to 0 by default.
To me it looks like you set m = 0 and then try to allocate by 0 length or how do you control the length of your dimensions?
Maybe edit your constructor to:
MyMatrix(int m, int n)
{
this->m = m;
this->n = n;
...
What's the meaning of the code below?
int **matrix = new int*[n]
What's the difference here between matrix and int*[n]?
It is an array of 'n' pointers, for which memory can be allocated and initialized in loop.
If n is 3, it is an array of 3 elements and each is pointer to int, can point to set of array of integer values like below.
matrix[0] -> Ox001 points to array of int [ 1 2 3 4]
matrix[1] -> Ox017 [ 5 6 7 8]
matrix[2] -> Ox024 [ 9 10 11 12]
Sample code like this
int **m = new int*[3];
for(auto i=0; i < 3; i++)
{
m[i] = new int[3];
for(auto j=0; j < 3; j++)
m[i][j] = 0;
}
for(auto i=0; i < 3; i++)
{
m[i] = new int[3];
for(auto j=0; j < 3; j++)
cout << m[i][j];
cout << "\n";
}
for instance there is cricket team and you need
Since you have Cricket* team;, this indicates you have one of two possible
situations:
1) a pointer to a single CricketPlayer (or any derived) type
2) a pointer to an array of CricketPlayer (but not derived) types.
What you want is a pointer to an array of CricketPlayer or derived types. So you
need the **.
You'll also need to allocate each team member individually and assign them to the array:
// 5 players on this team
CricketPlayer** team = new CricketPlayer*[5];
// first one is a bowler
team[0] = new Bowler();
// second one is a hitter
team[1] = new Hitter();
// etc
// then to deallocate memory
delete team[0];
delete team[1];
delete[] team;
In your query,
It can be understood as
int *matrix[]=new int*[n];
SO there are n pointers pointing to n places.
Because
int *foo;
foo=new int[5];
will also create 5 consecutive places but it is the same pointer.
In our case it is array of pointers
You need to notice some thing as follows:
int *p means that p is a pointer that points to an int variable or points to an array of int variables.
int* *p means that p is a pointer that points to an int* variable or points to an array of int* variables.
new int[5] is an array of 5 int variables.
new int*[5] is an array of 5 int* variables.
In this case, matrix is the second type so it can point to an array of int* variables so the statement:int **matrix = new int*[n] is legal
It means that you have declared a double pointer(of type int) called matrix and allocated an array of n int* pointers. Now you can use matrix[i] as an int* pointer (0 <= i < n). Later you might want to allocate memory to individual pointers as well like matrix[i] = new int[size];(size is an int or more appropriately size_t)
matrix is an object of type int **. This type is a pointer to pointer to int.
On the other hand, int * is a type, a pointer to int.
The expression:
new int*[n]
creates n adjacent objects of type int * somewhere in memory and returns a pointer to the first of them. In other words, it allocates and constructs n pointers to int; and returns a pointer to the first. Since the first (and each of them) are int *, the pointer pointing to the first is, in turn, of type int **.
It would be absolutely clear if you remember the operator associativity and precedence.
Going by that int *[n] will be interpreted by compiler : as array of " n pointer to integers".(as [ ] has greater precedence than *, so for easy understanding, compiler interprets it that way.).
Now comming to other side int ** matrix is pointer to pointer.
When you created an array of pointer,you basically have the address of the first location ,here first location stores an pointer to integer.
So,when you are storing the address of the first address of such array you will need pointer to a pointer to point the whole array.
//code for passing matrix as pointer and returning as a pointer
int ** update(int ** mat)
{
mat[0][1]=3;
return mat;
}
int main()
{ int k=4;
int **mat = new int*[k];
for(auto i=0; i < k; i++)
{
mat[i] = new int[k];
for(int j=0;j<k;j++)
{
if(i==j)
mat[i][j]=1;
else
mat[i][j]=0;
}
}
mat=update(mat);
for(auto i=0; i < k; i++)
{
for(auto j=0; j < k; j++)
cout << mat[i][j];
cout << "\n";
}
return 0;
}
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've been trying to make a program that adds 2 arrays of different size. But I would like to know to to dynamically increase the array size capacity? Ex: array[4] then upgrade the size to 2 to make array[6];?
EDIT: WIthout using vectors
I tried creating a new ptr but it does not work. I get the error: Read only variable is not assignable.
int *ptr2 = new int[a2.size];
// new ptr2 copies ptr1
for (int i=0; i<(a1.size); i++) {
ptr2[i] = a1.ptr[i];
}
// we want ptr1 to point to ptr2
for (int i=0; i<(a2.size); i++) {
ptr2[i] += a2.ptr[i];
}
delete [] a1.ptr;
a1.ptr=ptr2;
You can't change the size of the array, but you don't need to. You can just allocate a new array that's larger, copy the values you want to keep, delete the original array, and change the member variable to point to the new array.
Allocate a new[] array and store it in a temporary pointer.
Copy over the previous values that you want to keep.
Delete[] the old array.
Change the member variables, ptr and size to point to the new array and hold the new size.
int* newArr = new int[new_size];
std::copy(oldArr, oldArr + std::min(old_size, new_size), newArr);
delete[] oldArr;
oldArr = newArr;
#include<bits/stdc++.h>
using namespace std;
main(){
int *p = new int[5]; // locate memory in heap
int *q = new int[10];// locate memory in heap
for(int j=0; j<5;j++)
p[j] = j;
for(int i=0; i<5;i++)
q[i] = p[i];
delete []p;//Delete the old array 'p'
p = q; // Assign the pointer of 'q' to 'p'
q = NULL; // delete the location of pointer 'q'
return 0;
}
It may be late too answer but i'll explain some things to you..
Array Size cannot be increase because of contiguous memory allocation in the memory.
For Example => The address of the every location is
arr[5] => [2001,2002,2003,2004,2005]
Now, The main problem is if you allocate it to arr[10] so, as we don't know the next location 2006 will be free .
because array need to be in contiguous so, we won't be able to allocate memory
From my Suggestions use Vector or use dynamic Memory allocation in Cpp
int *old = new int[5];
int *nw = new int[10];
for (size_t i = 0; i < sizeof(old); i++)
nw[i] = old[i];
delete []old;
old = nw;
nw = NULL;
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p,*q;
int i;
p=(int *)malloc(5*sizeof(int));
p[0]=3;p[1]=5;p[2]=7;p[3]=9;p[4]=11;
q=(int *)malloc(10*sizeof(int));
for(i=0;i<5;i++)
q[i]=p[i];
free(p);
p=q;
q=NULL;
for(i=0;i<5;i++)
printf("%d \n",p[i]);
return 0;
}
I have created an array of doubles using the following code:
double *points = new double[(ii+1)*(jj+1)*(kk+1)*3];
I realize that in order to delete the array, all I have to do is:
delete[] points;
However; the array is created in a function (called create_points) that passes the address of the first element as follows:
return &points[0];
The code that calls this function then iterates through the address:
double *address = create_points(x_dim,y_dim,z_dim);
for(int k=0; k<x_dim+1; ++k)
for(int j=0; j<y_dim+1; ++j)
for(int i=0; i<z_dim+1; ++i) {
v[p_count].x = *address;
++address;
v[p_count].y = *address;
++address;
v[p_count].z = *address;
++address;
++p_count;
}
Now my question is, how do I properly delete the array of doubles that address is used to access? Can I simply go delete[] address, or do I have to do this some other way?
You cannot say delete[] address, doing so is undefined behavior. You have to delete it through a pointer to the original base address of the array. So, if you're going to increment the pointer, you need to remember the original pointer (or recompute it):
double *base_address = create_points(...);
double *address = base_address;
// do stuff with address, increment it, etc.
delete [] base_address
You have to give the right address. It does not suffice that the address lies within the allocated region.
Why not keep a copy of the pointer before starting the iteration? &points[0] == points
It is only defined behavior to delete what you allocated, and that would be the address returned via create_points.The best way would be to iterate over a temporary.
double *address = create_points(x_dim,y_dim,z_dim);
double *a = address;
for(int k=0; k<x_dim+1; ++k)
for(int j=0; j<y_dim+1; ++j)
for(int i=0; i<z_dim+1; ++i) {
v[p_count].x = *a;
++a;
v[p_count].y = *a;
++a;
v[p_count].z = *a;
++a;
++p_count;
}
delete[] address;