Sign in to follow this  
mylifemysoul

Nooby pointer question

Recommended Posts

mylifemysoul    100
Suddenly get a little big confused about pointers. Here are my questions: assume i defined a class A. Are the following all correct? And what's the difference? 1> A* a = new A(); delete a; 2> A* a=null; int num = 10; a = new A[num]; delete a[]; 3> A* a[10]; int num = 10; for(int i=0;i<num;i++) a[i] = new A(); For 3> can I use something like A** a and according to 'num', dynamically create the array?

Share this post


Link to post
Share on other sites
rip-off    10979
Apart from the fact that "null" isn't a valid value, yes they are all correct. However, #3 doesn't release the memory it allocates (you would need to loop over and delete each instance).

You can have a dynamically created array of pointers:

std::vector<A *> array;
for(int i = 0 ; i < 10 ; ++i) {
array.push_back(new A());
}

// ...

for(int i = 0 ; i < array.size() ; ++i) {
delete array[i];
}


Using the double pointer syntax:

int count = rand() % 1000;
A **array = new A*[count];
for(int i = 0 ; i < count ; ++i) {
array[i] = new A();
}

// ...

for(int i = 0 ; i < count ; ++i) {
delete array[i];
}
delete [] array;

Share this post


Link to post
Share on other sites
mylifemysoul    100
Quote:
Original post by rip-off
Apart from the fact that "null" isn't a valid value, yes they are all correct. However, #3 doesn't release the memory it allocates (you would need to loop over and delete each instance).

You can have a dynamically created array of pointers:
*** Source Snippet Removed ***
Using the double pointer syntax:
*** Source Snippet Removed ***


Thanks a lot. It's very helpful.

Share this post


Link to post
Share on other sites
Zahlman    1682
Quote:
Original post by rip-off
Apart from the fact that "null" isn't a valid value, yes they are all correct.


Not quite.

delete[] a[];

Also, there is almost never a reason to handle the allocations at this level. There are other, better reasons to understand pointers :)

Share this post


Link to post
Share on other sites
MARS_999    1627

int count = rand() % 1000;
A **array = new A*[count];
for(int i = 0 ; i &lt; count ; ++i) {
array[i] = new A();
}

// ...

for(int i = 0 ; i &lt; count ; ++i) {
delete array[i];
}
delete [] array;





Should be


int count = rand() % 1000;
A **array = new A*[count];
for(int i = 0 ; i &lt; count ; ++i) {
array[i] = new A();
}

// ...

for(int i = 0 ; i &lt; count ; ++i) {
delete []array[i];
}
delete []array;

Share this post


Link to post
Share on other sites
jyk    2094
Quote:
Original post by MARS_999
*** Source Snippet Removed ***


Should be

*** Source Snippet Removed ***
Why's that?

Share this post


Link to post
Share on other sites
Beyond_Repair    116
Quote:
Original post by MARS_999
*** Source Snippet Removed ***


Should be

*** Source Snippet Removed ***


Unless I see something wrong, no it shouldn't. You're getting an A* that points to a single element by the array[i] access, because it was allocated as new A().

Anyway, serves as a good example why plain C pointers for array indexing in C++ is an unnecessary source of bugs.

Share this post


Link to post
Share on other sites
DevFred    840
Quote:
Original post by Beyond_Repair
Anyway, serves as a good example why plain C pointers for array indexing in C++ is an unnecessary source of bugs.

But array indexing is defined with pointer arithmetic, so indexing through pointers is actually more natural than indexing with real arrays :)

x[y] is just syntactic sugar for *(x+y)

Share this post


Link to post
Share on other sites
jpetrie    13137
Quote:
Original post by MARS_999
jyk look here

link


That thread is talking about something else. The code you pasted above is still wrong:

int count = rand() % 1000;
A **array = new A*[count]; // HERE you allocate array with new[].
for(int i = 0 ; i < count ; ++i) {
array[i] = new A(); // HERE, array[i] is allocated with new.
}

// ...

for(int i = 0 ; i < count ; ++i) {
delete []array[i]; // HERE, array[i] is released with delete[] (WRONG)
}
delete []array; // HERE, array is released with delete[] (correct).


What you allocate with new, you release with delete. What you allocate with new[], you release with delete[]. Mix them, and you are wrong.

I assume you were referring to MikeP's correction of your first post in that linked thread; in that thread, you are allocating with new[] in one place and freeing with delete in another. In this thread you are doing exactly the opposite. Both are incorrect.

Share this post


Link to post
Share on other sites
MARS_999    1627
Quote:
Original post by jpetrie
Quote:
Original post by MARS_999
jyk look here

link


That thread is ta0lking about something else. The code you pasted above is still wrong:

int count = rand() % 1000;
A **array = new A*[count]; // HERE you allocate array with new[].
for(int i = 0 ; i < count ; ++i) {
array[i] = new A(); // HERE, array[i] is allocated with new.
}

// ...

for(int i = 0 ; i < count ; ++i) {
delete []array[i]; // HERE, array[i] is released with delete[] (WRONG)
}
delete []array; // HERE, array is released with delete[] (correct).


What you allocate with new, you release with delete. What you allocate with new[], you release with delete[]. Mix them, and you are wrong.

I assume you were referring to MikeP's correction of your first post in that linked thread; in that thread, you are allocating with new[] in one place and freeing with delete in another. In this thread you are doing exactly the opposite. Both are incorrect.


What are you talking about, first of all that code is his code I pasted from the rip-off

He does new with []

A **array = new A*[count];

Looks like a 2d array to me. So you will need to delete[]array[]

Unless I am missing something

Share this post


Link to post
Share on other sites
jpetrie    13137
Quote:

What are you talking about, first of all that code is his code I pasted from the rip-off

The code in my last post was the code you changed. Look at your first post in this thread, you say that "(some block of code) should be (some other block of code)". That second block of code is what I used in my previous post. That code differs from the original code rip-off provided in that you used the delete[] syntax inside the second loop, whereas rip-off used the delete syntax. He is correct, because the equivalent object from the first loop was allocated with new (not new[]).

Quote:

He does new with []

A **array = new A*[count];

Looks like a 2d array to me. So you will need to delete[]array[]

You will need to delete[] array. Not "delete[] array[]" -- that's not legal syntax at all and would not compile. It's not the deallocation of "array" you have done incorrectly -- in both rip-off's original code and your edited code, "array" is allocated with new[] and released with delete[].

What you did wrong was change the delete inside the second loop from a scalar delete to an array delete[]. That is wrong. You made no other changes to rip-off's code except to remove extra whitespace in the very last line ("delete [] array" became "delete []array" which is a superficial change that has no impact on the behavior or correctness of the program.

Share this post


Link to post
Share on other sites
Quote:
Original post by MARS_999
Looks like a 2d array to me. So you will need to delete[]array[]

Unless I am missing something

I do not believe 2D arrays use the syntax we are discussing. Consider this:
    typedef int* T;
T* array = new T[N];
To clarify, array is an array of pointers to other arrays. Replacing T with int* does not change how the code is interpreted.

EDIT: OK, you could call that a 2D array, but it doesn't have to be. The T's in array could point to pointers of singular integers, it could point to arrays of varying lengths, or anything you can imagine.

Share this post


Link to post
Share on other sites
jpetrie    13137
Quote:
I do not believe 2D arrays use the syntax we are discussing. Consider this:
typedef int* T;

T* array = new T[N];
To clarify, array is an array of pointers to other arrays. Replacing T with int* does not change how the code is interpreted.

No, 'array' is a pointer to T. T is a pointer to int. 'array' is a pointer to a pointer to int. It is not an array of pointers to pointers (that would require three levels of indirection, here we have only two).

This is a 2D array:

int a[2][2];

However, because of the overwhelming tendency for arrays to decay to pointers in C++, we often talk about double-pointers as "being 2D arrays," even when this is not strictly correct. Because of this we can also say that 'array' is an array of pointers -- taking array and dereferencing it would yield an int*. You could even say that it is an array of arrays, if you wanted, and nobody would really fault you much. But it's not an array of pointers to arrays.

Array and pointer are both terms of indirection, and the number of terms of indirection in the English name of a type must match the number of terms of indirection in the syntactical representation of the type -- in other words, the number of stars ('reference' and & also apply, but not to this particular discussion).

Regardless, it does not change the fact that allocating with scalar new and releasing that allocation with array delete -- as MARS_999's example did -- is wrong.

Share this post


Link to post
Share on other sites
MARS_999    1627
Quote:
Original post by jpetrie
Quote:
I do not believe 2D arrays use the syntax we are discussing. Consider this:
typedef int* T;

T* array = new T[N];
To clarify, array is an array of pointers to other arrays. Replacing T with int* does not change how the code is interpreted.

No, 'array' is a pointer to T. T is a pointer to int. 'array' is a pointer to a pointer to int. It is not an array of pointers to pointers (that would require three levels of indirection, here we have only two).

This is a 2D array:

int a[2][2];

However, because of the overwhelming tendency for arrays to decay to pointers in C++, we often talk about double-pointers as "being 2D arrays," even when this is not strictly correct. Because of this we can also say that 'array' is an array of pointers -- taking array and dereferencing it would yield an int*. You could even say that it is an array of arrays, if you wanted, and nobody would really fault you much. But it's not an array of pointers to arrays.

Array and pointer are both terms of indirection, and the number of terms of indirection in the English name of a type must match the number of terms of indirection in the syntactical representation of the type -- in other words, the number of stars ('reference' and & also apply, but not to this particular discussion).

Regardless, it does not change the fact that allocating with scalar new and releasing that allocation with array delete -- as MARS_999's example did -- is wrong.


Ah yes I see now I had tunnel vision I just couldn't see that he only used new A() I just couldn't see that until now... My bad! Sorry

Share this post


Link to post
Share on other sites
mylifemysoul    100
omg, didn't realize that my post had so many replies.

Thanks for all the discussions.

Thought the first reply was correct and went ahead and used part of it.

Anyway, I used 2D vector<> to avoid the new and delete for ** pointers. It turned out to be working quite well.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this