简体   繁体   中英

Handling of arrays of pointers in c++ and deleting them

I have created a test class (tc) which holds an array pointers to int.

class TC
{
public:
    int **values;
    TC(){values = new int*[10];
 };

When I instatiate an instance and do the following changes:

TC *a = new TC();    
int **values = &*a->values;
int **oldvalues = values;
values = new int*[10];
values[0] = oldvalues[0];
...
values[9] = oldvalues[9];

delete [] oldvalues;

for(int i = 0; i < 10; i++){
    delete values[i];
}

delete [] values;

Now comes the interesting part:

values = new int*[10];
*a->values = *values;

values[0] = new int(1);
values[9] = new int(10);
std::cout << *values[0] << " " << *values[9];

This prints out

1 10

But switching the two lines

values = new int*[10];
*a->values = *values;

to

*a->values = *new int*[10];    
values = &*a->values;

prints

182939382 10

Where the first part is some pointer.

Can someone explain why this happens? What makes the difference between the two ways to handle the pointers?

EDIT: I'd appreciate constructive input. As you might be able to tell I don't have any experience with c++ and pointer handling. So please help me understand the errors that I am committing.

This

*a->values = *values;

is the same as

 a->values[0] = values[0];

But values[0] is uninitialized, so you don't want to be reading from it.

If this is to long for you skip to the tldr part at the bottom, but that wont help you understand the problems, for that you need to read the rest.


my c is rusty but there are some highly strange parts:

lets start with this:

TC *a = new TC();    
int **values = &*a->values;
int **oldvalues = values;
values = new int*[10];
values[0] = oldvalues[0];
...
values[9] = oldvalues[9];

delete [] oldvalues;

for(int i = 0; i < 10; i++){
    delete values[i];
}

delete [] values;

TC *a = new TC();    

Perfectly fine

int **values = &*a->values;

lets look at the second half &*a->values; , step by step

  a              //pointer to tc
  a->values      //access values member of the tc a points to
                 //this is a int**
 *a->values      //dereference the int**, so we have a int*  
&*a->values;     //get the address of int*, so we have int** again

in short as stated in the comments you could just write a->values. Lets look further, you seem to be using int** to hold a pointer to an array of int pointers.

Now what does int **values = a->values; come down to? You copy a pointer , this means that **values and a->values now refer to the same address (slightly off, but for now consider Arrays as a pointer to the first element, that have to be defered with the index operator [] , otherwise they refer to the first element). This means you point to the same Array twice

values \\ \\ |- Array created by TC(){values = new int*[10]; / a->values /

int **oldvalues = values;

Basically you create a third pointer to the same array, for what reason?

values = new int*[10];

Here you overwrite values before you read once from it when initializing it to a->values .

values[0] = oldvalues[0];
...
values[9] = oldvalues[9];

noticing that you have two pointers you now copy the data. A loop or a function to copy chunks of memory could ease this, but I recommend a stl class, check out vector from the stl.

delete [] oldvalues;

you delete oldvalues , which is deleting the array that your TC -Class uses. While one needs to delete what one creates with new, this can be hell, if TC 's destructor tries to delete the array as well (though shall not call delete multiple times for the same object). Furthermore since your class seems to assume that values is alwazs valid, why not overwrite the values in the array?

for(int i = 0; i < 10; i++){
    delete values[i];
}
delete [] values;

you remember to delete all the integers before you delete the array, this is good, but why not overwrite them? Besides, this should be handled by the destructor as well, if you write one (you SHOULD). BUt what is dubious, why do you copy the elements, just to delete them?

FUrthermore, why don"t you use an integer array? is an array of pointers to integers really necessary?

This would be an int array [1, 2, 3, 7]. While this is an array of pointers: [see 1, see 2, see 4, see 5], in addition you have the following numbers at the following memory addresses 1@1, 2@2, 3@4, 7@5

For the array of pointers you have to do the following to get to a number:

*arrayOfPointers[3]

This does the following:

  1. the value of the 4th (for indexing start counting at 0) array element, see 5 is loaded
  2. the value is dereferenced which means the computer looks in the memory location with the label five and sees 7

For an Array of integers aarrayOfIntegers[3] is sufficient which saves one level of indirection.


to the last snippet:

values = new int*[10];

you create an array to replace the one you just deleted.

*a->values = *values;

you assign the first element, see Ben Voigts answer and remember that an array is just a pointer to the first element. SInce you dereference it you copy the first array element. You can put these two lines into one and remove the mistake by putting:

a->values = new int*[10];

Back to your code:

values[0] = new int(1);
values[9] = new int(10);
std::cout << *values[0] << " " << *values[9];

You went through all this trouble just ot change the first and last number....


TLDR, shorter solution

Let me show you haow it can be done in a shorter way:

class TC { public: int *values; TC() : values(new int[10]) {} //google initializer list ~TC(){ delete values; } //destructor, called when your instance needs to be cleaned up };

the usage:

TC *a = new TC();
a->values[0] = 1;
a->values[9] =10:
std::cout << a->values[0] << " " << a->values[9];

or without pointers

TC a();
a.values[0] = 1;
a.values[9] =10:
std::cout << a.values[0] << " " << a.values[9];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM