Reputation: 226
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.
Upvotes: 0
Views: 138
Reputation: 4975
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:
4th
(for indexing start counting at 0) array element, see 5
is loaded7
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];
Upvotes: 1
Reputation: 283624
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.
Upvotes: 4