delete[] p or delete[] *p

G

Goran

"Goran" <[email protected]> wrote in message
Yes I have. Read this again:

This is your code that is wrong not the cast.

Problem line is

Base (*p2)[3] = (Base (*)[3])new Derived[2][3];

and __you__ wrote it first.

I changed Base in a way that shows that your code won't work. But I
did not change the offending part.

It looks like you think that "not UB" means "seems to work on my
code"?
You cannot even explain what
is wrong with the cast in your opinion , its just wrong?

My explanation is fine compared to your lack of understanding what
"proof by contradiction" means.
I provided the following code as an alternative which you snipped and
ignored. And you replaced it with your buggy shit code.

Not true. Nothing in what __I__ wrote is wrong. Errors are in what
__you__ have written, that I took over. My purpose was clear: to show
you __how__ and __why__ what you wrote fails. You really seem to think
that "not UB" means "seems to work on my code".
The following is the same C cast but in C++ style, is this also UB in your
mind?
template <typename T, int S>
T* foo(){
return static_cast<T*>:):eek:perator new(S * sizeof(T)));}
int main() {
int (*p)[6] = foo<int[6], 6>();

It does not matter whether cast is C or C++-style.

Yes, this is UB, and it's __much__ worse than your old examples. If
you try this on __any__ type that has a constructor, this is going to
fail __massively__. Just put e.g. this in your main:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

It's your use of the code that produces undefined behaviour, this code is
identical to the code used in std::allocator.

.... In some implementation you saw somewhere, you mean, right? Cause I
don't think standard prescribes exact code for
std::allocator::allocate.
Just because you can use this code in a way that produces UB does not mean
the code itself produces UB.

How do I know that your goal was to return uninitialized storage?
That's very unusual, clearly documented for allocator::allocate, and
in no way implied or visible by your code.
If you theory was correct every container in the std lib would produce UB

I don't do theory. I do practice. I had no way of knowing that your
goal was to return uninitialized memory from "f". (In fact, I think
you didn't even realize what you did before reading my response). In
practice, you don't do that without clearly stating so. If you do, I
am glad you I don't work where you work. In practice, also, all
containers __construct__ objects in storage returned by
allocator::allocate (what, did you think otherwise!?).
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

std::string (*p)[6] = foo<string[6], 6>();

And watch this lunacy of yours fail.

You can legally use static_cast to go from void* to some other type,
that's OK, but that does not mean that code can't exhibit UB.

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
As I said above you can make almost any code produce UB if you use it
incorrectly. It's not the code I posted that produces UB , its your
incorrect useage of the code.

My usage is just fine given the interface of "f". It returns T*. Why
__wouldn't__ I be able to use it with std::string? Answer: because
either code itself is bad, either it's intention is unclear or poorly
documented.
If you think the code I posted produces UB then just compare that code to
the constructor in std::allocator.  As the code is identical you must also
think std::allocator produces UB.

That conclusion is wrong and based on poor logic. No, I do not think
that allocator::allocate (one that does static_cast<T*>:):new(sizeof T
* n), which, I claim, is not __required__ by the standard) produces
UB, because I know that whatever it produces will be constructed
before reaching any other code, or else, implementation has a bug.
Your function, OTOH, spit out uninitialized storage as if it was
something people do as a matter of fact.

(By the way, there's no reason to mention any constructor. You are
clearly talking about allocator::allocate, and that does no
construction whatsoever).

Goran.
 
P

Paul

Goran said:
Yes I have. Read this again:

This is your code that is wrong not the cast.

Problem line is

Base (*p2)[3] = (Base (*)[3])new Derived[2][3];

and __you__ wrote it first.

I changed Base in a way that shows that your code won't work. But I
did not change the offending part.

It looks like you think that "not UB" means "seems to work on my
code"?
You cannot even explain what
is wrong with the cast in your opinion , its just wrong?

My explanation is fine compared to your lack of understanding what
"proof by contradiction" means.
I provided the following code as an alternative which you snipped and
ignored. And you replaced it with your buggy shit code.

Not true. Nothing in what __I__ wrote is wrong. Errors are in what
__you__ have written, that I took over. My purpose was clear: to show
you __how__ and __why__ what you wrote fails. You really seem to think
that "not UB" means "seems to work on my code".
The following is the same C cast but in C++ style, is this also UB in
your
mind?
template <typename T, int S>
T* foo(){
return static_cast<T*>:):eek:perator new(S * sizeof(T)));}
int main() {
int (*p)[6] = foo<int[6], 6>();

It does not matter whether cast is C or C++-style.

Yes, this is UB, and it's __much__ worse than your old examples. If
you try this on __any__ type that has a constructor, this is going to
fail __massively__. Just put e.g. this in your main:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

It's your use of the code that produces undefined behaviour, this code is
identical to the code used in std::allocator.

.... In some implementation you saw somewhere, you mean, right? Cause I
don't think standard prescribes exact code for
std::allocator::allocate.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You said this code produced UB , so even if it's only one implementation you
still say this particular implementation of the std lib produces UB.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Just because you can use this code in a way that produces UB does not mean
the code itself produces UB.

How do I know that your goal was to return uninitialized storage?
That's very unusual, clearly documented for allocator::allocate, and
in no way implied or visible by your code.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Your argument is that an int* points to a single int and not to an array, or
have you forgotten that?
I have said that an int* can point to a single int or an array of int. I am
trying to show you that pointers can point to anything.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
If you theory was correct every container in the std lib would produce UB

I don't do theory. I do practice. I had no way of knowing that your
goal was to return uninitialized memory from "f". (In fact, I think
you didn't even realize what you did before reading my response). In
practice, you don't do that without clearly stating so. If you do, I
am glad you I don't work where you work. In practice, also, all
containers __construct__ objects in storage returned by
allocator::allocate (what, did you think otherwise!?).
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
No? well funnily enough thats what new does, it returns memory. Strange how
you couldn't work that out.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

std::string (*p)[6] = foo<string[6], 6>();

And watch this lunacy of yours fail.

You can legally use static_cast to go from void* to some other type,
that's OK, but that does not mean that code can't exhibit UB.

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
As I said above you can make almost any code produce UB if you use it
incorrectly. It's not the code I posted that produces UB , its your
incorrect useage of the code.

My usage is just fine given the interface of "f". It returns T*. Why
__wouldn't__ I be able to use it with std::string? Answer: because
either code itself is bad, either it's intention is unclear or poorly
documented.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Your usage is not fine , it produces UB.
The code presented doesn't produceUB without your code. Its behaviour is
perfectly defined until your code is added.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
If you think the code I posted produces UB then just compare that code to
the constructor in std::allocator. As the code is identical you must also
think std::allocator produces UB.

That conclusion is wrong and based on poor logic. No, I do not think
that allocator::allocate (one that does static_cast<T*>:):new(sizeof T
* n), which, I claim, is not __required__ by the standard) produces
UB, because I know that whatever it produces will be constructed
before reaching any other code, or else, implementation has a bug.
Your function, OTOH, spit out uninitialized storage as if it was
something people do as a matter of fact.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
The code is perfectly legal and defined code, it can be used anywhere by any
procedure. Your incorrect usage produces UB not the code on its own.
If a piece of code allocates an array of Cats and you treat it like an array
of Dogs your code is wrong , not the code that creates the array of Cats.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


(By the way, there's no reason to mention any constructor. You are
clearly talking about allocator::allocate, and that does no
construction whatsoever).
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Whether its a constructor or not is irrelevant to the discussion, this is
simply an avoidance tactic to change the subject. You say this code produces
UB when it is actually YOUR code that produces the UB.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 
G

Goran

Problem line is
Base (*p2)[3] = (Base (*)[3])new Derived[2][3];
and __you__ wrote it first.
I changed Base in a way that shows that your code won't work. But I
did not change the offending part.
It looks like you think that "not UB" means "seems to work on my
code"?
My explanation is fine compared to your lack of understanding what
"proof by contradiction" means.
Not true. Nothing in what __I__ wrote is wrong. Errors are in what
__you__ have written, that I took over. My purpose was clear: to show
you __how__ and __why__ what you wrote fails. You really seem to think
that "not UB" means "seems to work on my code".
The following is the same C cast but in C++ style, is this also UB in
your
mind?
template <typename T, int S>
T* foo(){
return static_cast<T*>:):eek:perator new(S * sizeof(T)));}
int main() {
int (*p)[6] = foo<int[6], 6>();
}
It does not matter whether cast is C or C++-style.
Yes, this is UB, and it's __much__ worse than your old examples. If
you try this on __any__ type that has a constructor, this is going to
fail __massively__. Just put e.g. this in your main:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
It's your use of the code that produces undefined behaviour, this code is
identical to the code used in std::allocator.

... In some implementation you saw somewhere, you mean, right? Cause I
don't think standard prescribes exact code for
std::allocator::allocate.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You said this code produced UB , so even if it's only one implementation you
still say this particular implementation of the std lib produces UB.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

No, your conclusion is wrong. The differences between your code and
the standard library one are:

* standard library won't ever pass said pointer to code that can use
it to produce UB
* standard library __in question__ knows that it's safe to go from
void* allocated from ::eek:perator new to T*, because standard library is
tied to implementation. As far as I know, this passage is __not
guaranteed__ by the standard. The problem, obviously, are alignment
requirements of the platform (e.g. ::eek:perator new returns pointers
aligned on 4-byte boundary, but e.g. double must be aligned on 8-byte
boundary, in which case the very cast inside f is UB).
How do I know that your goal was to return uninitialized storage?
That's very unusual, clearly documented for allocator::allocate, and
in no way implied or visible by your code.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Your argument is that an int* points to a single int and not to an array,or
have you forgotten that?

Irrelevant. Your question __here__ was if the code you offered was OK.
It wasn't (or at best, it was hardly OK).
I have said that an int* can point to a single int or an array of int. I am
trying to show you that pointers can point to anything.

Why, yes, they can, in hands of people like you, who cast nilly-willy
and claim that code is correct because they see it works, on code they
need, on implementation they need. Things are, however, slightly more
complicated and their very code might not work tomorrow on their very
implementation (like when they use "f" with std::string).

That said... In your code, "p" is int(*)[6]. Type-wise, f returns that
very same thing. You showed __nothing__ on the lines of your argument.
In addition, implementation of f is just bad, because it returns
uninitialized storage, and because it's implementation-dependent.

But fair enough. So your argument is that a pointer can point to __an
array__. If so, how do you explain what is happening here?

int a[2][2] = {1, 2, 3, 4};
int* p = a[0]; // By your argument, p points to an array, right?
assert(*p = 1); // OK;
p++;
assert(*p==2);

Now, hang on! p points to an array. I incremented p. Normally, when
you increment a pointer, it points to a next element. If p points to
an __array__ (a[0]), and I increment it, then it should point to a[1].
Yet, it doesn't. Why? Perhaps because p actually points to a __first
element__ of an array? (proof by contradiction, remember that?)

In other words... Saying that pointer points to an array leads to
surprising results when employing simple logic to pointers, array-to-
pointer conversion, pointer arithmetic and who knows what else. Saying
that is __choke full__ of contradictions (first of them obviously
being what pointer __type__ is).

People do say what you say ("p points to _that_ array"), and that's,
quite frankly, OK as far as ease of communication is concerned. What
is __implied__, however, is that pointer actually points to the first
element. Muddling waters like you're trying to do serves no-one.

Goran.
 
P

Paul

Goran said:
Problem line is
Base (*p2)[3] = (Base (*)[3])new Derived[2][3];
and __you__ wrote it first.
I changed Base in a way that shows that your code won't work. But I
did not change the offending part.
It looks like you think that "not UB" means "seems to work on my
code"?
My explanation is fine compared to your lack of understanding what
"proof by contradiction" means.
Not true. Nothing in what __I__ wrote is wrong. Errors are in what
__you__ have written, that I took over. My purpose was clear: to show
you __how__ and __why__ what you wrote fails. You really seem to think
that "not UB" means "seems to work on my code".
The following is the same C cast but in C++ style, is this also UB in
your
mind?
template <typename T, int S>
T* foo(){
return static_cast<T*>:):eek:perator new(S * sizeof(T)));}
int main() {
int (*p)[6] = foo<int[6], 6>();
}
It does not matter whether cast is C or C++-style.
Yes, this is UB, and it's __much__ worse than your old examples. If
you try this on __any__ type that has a constructor, this is going to
fail __massively__. Just put e.g. this in your main:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
It's your use of the code that produces undefined behaviour, this code
is
identical to the code used in std::allocator.

... In some implementation you saw somewhere, you mean, right? Cause I
don't think standard prescribes exact code for
std::allocator::allocate.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You said this code produced UB , so even if it's only one implementation
you
still say this particular implementation of the std lib produces UB.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

No, your conclusion is wrong. The differences between your code and
the standard library one are:

* standard library won't ever pass said pointer to code that can use
it to produce UB
* standard library __in question__ knows that it's safe to go from
void* allocated from ::eek:perator new to T*, because standard library is
tied to implementation. As far as I know, this passage is __not
guaranteed__ by the standard. The problem, obviously, are alignment
requirements of the platform (e.g. ::eek:perator new returns pointers
aligned on 4-byte boundary, but e.g. double must be aligned on 8-byte
boundary, in which case the very cast inside f is UB).
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Its up to you to use the code responsibly. According, to you every piece of
code that is breakable would produce UB.
It was clear what the piece of code posted did. You, either deliberately or
unknowingly, used this code inappropriately to produce an error.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

How do I know that your goal was to return uninitialized storage?
That's very unusual, clearly documented for allocator::allocate, and
in no way implied or visible by your code.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Your argument is that an int* points to a single int and not to an array,
or
have you forgotten that?

Irrelevant. Your question __here__ was if the code you offered was OK.
It wasn't (or at best, it was hardly OK).
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Yes quite true , your argument is quite irrelevant.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
I have said that an int* can point to a single int or an array of int. I
am
trying to show you that pointers can point to anything.

Why, yes, they can, in hands of people like you, who cast nilly-willy
and claim that code is correct because they see it works, on code they
need, on implementation they need. Things are, however, slightly more
complicated and their very code might not work tomorrow on their very
implementation (like when they use "f" with std::string).

That said... In your code, "p" is int(*)[6]. Type-wise, f returns that
very same thing. You showed __nothing__ on the lines of your argument.
In addition, implementation of f is just bad, because it returns
uninitialized storage, and because it's implementation-dependent.

But fair enough. So your argument is that a pointer can point to __an
array__. If so, how do you explain what is happening here?

int a[2][2] = {1, 2, 3, 4};
int* p = a[0]; // By your argument, p points to an array, right?
assert(*p = 1); // OK;
p++;
assert(*p==2);

Now, hang on! p points to an array. I incremented p. Normally, when
you increment a pointer, it points to a next element. If p points to
an __array__ (a[0]), and I increment it, then it should point to a[1].
Yet, it doesn't. Why? Perhaps because p actually points to a __first
element__ of an array? (proof by contradiction, remember that?)

In other words... Saying that pointer points to an array leads to
surprising results when employing simple logic to pointers, array-to-
pointer conversion, pointer arithmetic and who knows what else. Saying
that is __choke full__ of contradictions (first of them obviously
being what pointer __type__ is).

People do say what you say ("p points to _that_ array"), and that's,
quite frankly, OK as far as ease of communication is concerned. What
is __implied__, however, is that pointer actually points to the first
element. Muddling waters like you're trying to do serves no-one.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Its not me you argue agaisnt , its the C++ language. It doesn't matter how
much you try to explian how you think the type system works, if you had any
clue you'd understand that the asm PTR directive doesn't define what is
pointed to, and the C++ type doesn't define what is pointed to.
If you treat a pointer to an array, as if it doesn't point to an array then
you are going to make mistakes. And its your codes' bad use of pointers that
is erroneous here.

My original question was:
Suppose I have the following code:

int (*p)[5] = (int (*)[5])new int[5];

How do I delete the allocated memory?

Now you said this code produced UB , and I have asked you to ellaborate,
where exactly is the UB?
You have answered this by adding some of your own code that uses my code
irresponsibly but that is your code that causes the error , not my code.

The said pointer type points to a 1d array, but its type suggests it points
to a 2d array or the &address of a 1d array.


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 
V

Virchanza

Hi,
Suppose I have the following code:

int (*p)[5] = (int (*)[5])new int[5];

How do I delete the allocated memory?
Is it:
a) delete[] p;
b) delete[] *p;
c) delete[] (int*)p;

?? Any ideas??

When you use the "new" operator to create an array, it gives you the
address of the first element in the array.

So if the array is "int[5]", the address of the first element will be
"int*".

If you want the address of the first element to be "int(*)[5]", then
you need to do:

int (*p)[5] = new int[1][5];

delete [] p;
 
P

Paul

Virchanza said:
How do I delete the allocated memory?
Is it:
a) delete[] p;
b) delete[] *p;
c) delete[] (int*)p;

?? Any ideas??

When you use the "new" operator to create an array, it gives you the
address of the first element in the array.

So if the array is "int[5]", the address of the first element will be
"int*".

If you want the address of the first element to be "int(*)[5]", then
you need to do:

int (*p)[5] = new int[1][5];

delete [] p;

Ah create a 1d array in 2d format. Nice simple solution, I like it.
 
G

Goran

First things first. You do understand now that casts you tried to
pull
off are UB, right?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
What exactly is UB? Casting in general produces UB, or only when I
cast?
In your post
here:http://groups.google.com/group/comp.lang.c++/msg/1948e01fd0971cac,
I claimed that first two casts were UB. You claimed that they were
not. I proved you that they were (read back, please).
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You haven't proved anything is UB,
Yes I have. Read this again:
http://groups.google.com/group/comp.lang.c++/msg/e274c527afabc5f4
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
This is your code that is wrong not the cast.
Problem line is
Base (*p2)[3] = (Base (*)[3])new Derived[2][3];
and __you__ wrote it first.
I changed Base in a way that shows that your code won't work. But I
did not change the offending part.
It looks like you think that "not UB" means "seems to work on my
code"?
You cannot even explain what
is wrong with the cast in your opinion , its just wrong?
My explanation is fine compared to your lack of understanding what
"proof by contradiction" means.
I provided the following code as an alternative which you snipped and
ignored. And you replaced it with your buggy shit code.
Not true. Nothing in what __I__ wrote is wrong. Errors are in what
__you__ have written, that I took over. My purpose was clear: to show
you __how__ and __why__ what you wrote fails. You really seem to think
that "not UB" means "seems to work on my code".
The following is the same C cast but in C++ style, is this also UB in
your
mind?
template <typename T, int S>
T* foo(){
return static_cast<T*>:):eek:perator new(S * sizeof(T)));}
int main() {
int (*p)[6] = foo<int[6], 6>();
}
It does not matter whether cast is C or C++-style.
Yes, this is UB, and it's __much__ worse than your old examples. If
you try this on __any__ type that has a constructor, this is going to
fail __massively__. Just put e.g. this in your main:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
It's your use of the code that produces undefined behaviour, this code
is
identical to the code used in std::allocator.
... In some implementation you saw somewhere, you mean, right? Cause I
don't think standard prescribes exact code for
std::allocator::allocate.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You said this code produced UB , so even if it's only one implementation
you
still say this particular implementation of the std lib produces UB.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

No, your conclusion is wrong. The differences between your code and
the standard library one are:

* standard library won't ever pass said pointer to code that can use
it to produce UB
* standard library __in question__ knows that it's safe to go from
void* allocated from ::eek:perator new to T*, because standard library is
tied to implementation. As far as I know, this passage is __not
guaranteed__ by the standard. The problem, obviously, are alignment
requirements of the platform (e.g. ::eek:perator new returns pointers
aligned on 4-byte boundary, but e.g. double must be aligned on 8-byte
boundary, in which case the very cast inside f is UB).
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Its up to you to use the code responsibly. According, to you every piece of
code that is breakable would  produce UB.

The problem is rather that, according to you, it's somehow OK to
return uninitialized storage under the guise of T*. It's not (or at
least, it has to be clearly stated).
It was clear what the piece of code posted did. You, either deliberately or
unknowingly, used this code inappropriately to produce an error.

Yes, it was deliberate. Because if you try to actually __construct__
objects in the storage you allocated, things do not go so well, now do
they? And if you don't construct, well, so you managed to legally cast
a void* pointer to T*, which is rather underwhelming. Your cast is
legal, which does not make code good (or interesting, for that
matter).
Its not me you argue agaisnt , its the C++ language. It doesn't matter how
much you try to explian how you think the type system works, if you had any
clue you'd understand that the asm PTR directive doesn't define what is
pointed to,

Oh, come on! asm PTR directive might exist in some assembler toolkit,
but it bears no relevance to the language. Even asm itself is
implementation-dependent. It also bears no relevance to malloc/free,
or any operator new. Why are you mentioning that?
and the C++ type doesn't define what is pointed to.

It does, and it's completely clear: T* points to an object of type T.
What are you on about!?
If you treat a pointer to an array, as if it doesn't point to an array then
you are going to make mistakes. And its your codes' bad use of pointers that
is erroneous here.

Yes, but there's a purpose: it's to show you what your insistence on
saying that e.g. "p" in "p = new TYPE" points to an array leads to.
It's just fraught with danger, and there's no practical purpose (or at
least, you failed to show one).
My original question was:
Suppose I have the following code:

int (*p)[5] = (int (*)[5])new int[5];

How do I delete the allocated memory?

And my original answer was: you allocated an array of ints, you should
call delete[] on the pointer to the first element of that array, which
was returned from "new. Easy as a pie. That is, your code should be:

int *p = new int[5];
delete [] p;

I have no idea why you want to use all these casts. You failed to
explain that. E.g. example you offered here:

http://groups.google.com/group/comp.lang.c++/msg/d0013eb81268f0ce

was pretty bad code, and you avoided to explain what you really
wanted. The other example, with Base and Derived, was also bad,
because it could only work when indexing a pointer to Base resulted in
a same value as when indexing a pointer to Derived> That is, I think,
implementation-dependent, and also rather constraining in practice.

Goran.
 
P

Paul

First things first. You do understand now that casts you tried
to
pull
off are UB, right?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
What exactly is UB? Casting in general produces UB, or only when
I
cast?
In your post
here:http://groups.google.com/group/comp.lang.c++/msg/1948e01fd0971cac,
I claimed that first two casts were UB. You claimed that they were
not. I proved you that they were (read back, please).
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You haven't proved anything is UB,
Yes I have. Read this again:
http://groups.google.com/group/comp.lang.c++/msg/e274c527afabc5f4
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
This is your code that is wrong not the cast.
Problem line is
Base (*p2)[3] = (Base (*)[3])new Derived[2][3];
and __you__ wrote it first.
I changed Base in a way that shows that your code won't work. But I
did not change the offending part.
It looks like you think that "not UB" means "seems to work on my
code"?
You cannot even explain what
is wrong with the cast in your opinion , its just wrong?
My explanation is fine compared to your lack of understanding what
"proof by contradiction" means.
I provided the following code as an alternative which you snipped
and
ignored. And you replaced it with your buggy shit code.
Not true. Nothing in what __I__ wrote is wrong. Errors are in what
__you__ have written, that I took over. My purpose was clear: to show
you __how__ and __why__ what you wrote fails. You really seem to think
that "not UB" means "seems to work on my code".
The following is the same C cast but in C++ style, is this also UB
in
your
mind?
template <typename T, int S>
T* foo(){
return static_cast<T*>:):eek:perator new(S * sizeof(T)));}
int main() {
int (*p)[6] = foo<int[6], 6>();
}
It does not matter whether cast is C or C++-style.
Yes, this is UB, and it's __much__ worse than your old examples. If
you try this on __any__ type that has a constructor, this is going to
fail __massively__. Just put e.g. this in your main:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
It's your use of the code that produces undefined behaviour, this code
is
identical to the code used in std::allocator.
... In some implementation you saw somewhere, you mean, right? Cause I
don't think standard prescribes exact code for
std::allocator::allocate.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You said this code produced UB , so even if it's only one implementation
you
still say this particular implementation of the std lib produces UB.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

No, your conclusion is wrong. The differences between your code and
the standard library one are:

* standard library won't ever pass said pointer to code that can use
it to produce UB
* standard library __in question__ knows that it's safe to go from
void* allocated from ::eek:perator new to T*, because standard library is
tied to implementation. As far as I know, this passage is __not
guaranteed__ by the standard. The problem, obviously, are alignment
requirements of the platform (e.g. ::eek:perator new returns pointers
aligned on 4-byte boundary, but e.g. double must be aligned on 8-byte
boundary, in which case the very cast inside f is UB).
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Its up to you to use the code responsibly. According, to you every piece
of
code that is breakable would produce UB.

The problem is rather that, according to you, it's somehow OK to
return uninitialized storage under the guise of T*. It's not (or at
least, it has to be clearly stated).
It was clear what the piece of code posted did. You, either deliberately
or
unknowingly, used this code inappropriately to produce an error.

Yes, it was deliberate. Because if you try to actually __construct__
objects in the storage you allocated, things do not go so well, now do
they? And if you don't construct, well, so you managed to legally cast
a void* pointer to T*, which is rather underwhelming. Your cast is
legal, which does not make code good (or interesting, for that
matter).
Its not me you argue agaisnt , its the C++ language. It doesn't matter how
much you try to explian how you think the type system works, if you had
any
clue you'd understand that the asm PTR directive doesn't define what is
pointed to,

Oh, come on! asm PTR directive might exist in some assembler toolkit,
but it bears no relevance to the language. Even asm itself is
implementation-dependent. It also bears no relevance to malloc/free,
or any operator new. Why are you mentioning that?
and the C++ type doesn't define what is pointed to.

It does, and it's completely clear: T* points to an object of type T.
What are you on about!?
If you treat a pointer to an array, as if it doesn't point to an array
then
you are going to make mistakes. And its your codes' bad use of pointers
that
is erroneous here.

Yes, but there's a purpose: it's to show you what your insistence on
saying that e.g. "p" in "p = new TYPE" points to an array leads to.
It's just fraught with danger, and there's no practical purpose (or at
least, you failed to show one).
My original question was:
Suppose I have the following code:

int (*p)[5] = (int (*)[5])new int[5];

How do I delete the allocated memory?

And my original answer was: you allocated an array of ints, you should
call delete[] on the pointer to the first element of that array, which
was returned from "new. Easy as a pie. That is, your code should be:

int *p = new int[5];
delete [] p;

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
No, All you said was that is was UB.
 
P

Paul

Leigh Johnston said:
Virchanza said:
How do I delete the allocated memory?
Is it:
a) delete[] p;
b) delete[] *p;
c) delete[] (int*)p;

?? Any ideas??

When you use the "new" operator to create an array, it gives you the
address of the first element in the array.

So if the array is "int[5]", the address of the first element will be
"int*".

If you want the address of the first element to be "int(*)[5]", then
you need to do:

int (*p)[5] = new int[1][5];

delete [] p;

Ah create a 1d array in 2d format. Nice simple solution, I like it.

I gave an example of doing the above weeks ago but as you are so blinkered
you missed it; this is further proof that you don't properly read what
people (or Standards) actually say.
I don't bother to read what you say because 99% of the time its either
bullshit or incorrrect.
You are a proven idiot and you did not respond to this thread weeeks ago.
 
P

Paul

Leigh Johnston said:
How do I delete the allocated memory?
Is it:
a) delete[] p;
b) delete[] *p;
c) delete[] (int*)p;

?? Any ideas??

When you use the "new" operator to create an array, it gives you the
address of the first element in the array.

So if the array is "int[5]", the address of the first element will be
"int*".

If you want the address of the first element to be "int(*)[5]", then
you need to do:

int (*p)[5] = new int[1][5];

delete [] p;

Ah create a 1d array in 2d format. Nice simple solution, I like it.

I gave an example of doing the above weeks ago but as you are so
blinkered you missed it; this is further proof that you don't properly
read what people (or Standards) actually say.
I don't bother to read what you say because 99% of the time its either
bullshit or incorrrect.
You are a proven idiot and you did not respond to this thread weeeks ago.

You are the one full of bullshit:

On 17/03/2011 22:14, Leigh Johnston wrote:

[...]

Maybe the following will help you understand the semantic differences
involved:

int main()
{
int* p1 = new int[42]; // 'p1' is a pointer to the first element
of an array
int (*p2)[42] = new int[1][42]; // 'p2' is a pointer to an array
}

http://groups.google.com/group/comp.lang.c++/browse_thread/thread/8cb33b21e1a4b794/2646056e0efa270a
That was a different thread and the point you were, incorrectly, trying to
make was that p1 didn't point to an array.
TY for confirming that you are indeed a bullshitter.
 
G

Goran

My original question was:
Suppose I have the following code:
int (*p)[5] = (int (*)[5])new int[5];
How do I delete the allocated memory?

And my original answer was: you allocated an array of ints, you should
call delete[] on the pointer to the first element of that array, which
was returned from "new. Easy as a pie. That is, your code should be:

int *p = new int[5];
delete [] p;

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
No, All you said was that is was UB.

Not true.

This:

http://groups.google.com/group/comp.lang.c++/msg/b8ed179f99440d11

was my first response to your question.

Goran.
 
P

Paul

My original question was:
Suppose I have the following code:
int (*p)[5] = (int (*)[5])new int[5];
How do I delete the allocated memory?

And my original answer was: you allocated an array of ints, you should
call delete[] on the pointer to the first element of that array, which
was returned from "new. Easy as a pie. That is, your code should be:

int *p = new int[5];
delete [] p;

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
No, All you said was that is was UB.

Not true.

This:

http://groups.google.com/group/comp.lang.c++/msg/b8ed179f99440d11

was my first response to your question.

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Yes and after I answered this you said the cast was UB. And thats what this
particular subthread has been about.
 
P

Paul

Leigh Johnston said:
How do I delete the allocated memory?
Is it:
a) delete[] p;
b) delete[] *p;
c) delete[] (int*)p;

?? Any ideas??

When you use the "new" operator to create an array, it gives you the
address of the first element in the array.

So if the array is "int[5]", the address of the first element will
be
"int*".

If you want the address of the first element to be "int(*)[5]", then
you need to do:

int (*p)[5] = new int[1][5];

delete [] p;

Ah create a 1d array in 2d format. Nice simple solution, I like it.

I gave an example of doing the above weeks ago but as you are so
blinkered you missed it; this is further proof that you don't properly
read what people (or Standards) actually say.

I don't bother to read what you say because 99% of the time its either
bullshit or incorrrect.
You are a proven idiot and you did not respond to this thread weeeks
ago.

You are the one full of bullshit:

On 17/03/2011 22:14, Leigh Johnston wrote:

[...]

Maybe the following will help you understand the semantic differences
involved:

int main()
{
int* p1 = new int[42]; // 'p1' is a pointer to the first element of an
array
int (*p2)[42] = new int[1][42]; // 'p2' is a pointer to an array
}

http://groups.google.com/group/comp.lang.c++/browse_thread/thread/8cb33b21e1a4b794/2646056e0efa270a
That was a different thread and the point you were, incorrectly, trying
to make was that p1 didn't point to an array.

Why should I care if it is different thread of yours? You have a habit of
starting a new thread to hide the fact that you have lost an argument in
an existing thread.

Incorrect? p1 did point to an array.
TY for confirming that you are indeed a bullshitter.

What am I bullshitting about exactly?
I don't know what you are bullshitting about because its bullshit.
Apparently you don't know what you are bullshitting about either, so stop
your bullshit please.
 
P

Paul

Leigh Johnston said:
On 04/04/2011 20:20, Paul wrote:
I gave an example of doing the above weeks ago but as you are so
blinkered you missed it; this is further proof that you don't
properly
read what people (or Standards) actually say.

I don't bother to read what you say because 99% of the time its
either
bullshit or incorrrect.
You are a proven idiot and you did not respond to this thread weeeks
ago.

You are the one full of bullshit:

On 17/03/2011 22:14, Leigh Johnston wrote:

[...]

Maybe the following will help you understand the semantic differences
involved:

int main()
{
int* p1 = new int[42]; // 'p1' is a pointer to the first element of an
array
int (*p2)[42] = new int[1][42]; // 'p2' is a pointer to an array
}

http://groups.google.com/group/comp.lang.c++/browse_thread/thread/8cb33b21e1a4b794/2646056e0efa270a



That was a different thread and the point you were, incorrectly, trying
to make was that p1 didn't point to an array.

Why should I care if it is different thread of yours? You have a habit
of starting a new thread to hide the fact that you have lost an
argument in an existing thread.

Incorrect? p1 did point to an array.

TY for confirming that you are indeed a bullshitter.

What am I bullshitting about exactly?
I don't know what you are bullshitting about because its bullshit.
Apparently you don't know what you are bullshitting about either, so
stop your bullshit please.

As you are a troll I suspected that you would deliberately ignore my
correction: trying to make something out of a typo is a typical troll
trait.

So just to be clear:

troll* p1 = new paul[1]; // p1 is a pointer to a troll
troll(*p2)[1] = new troll[1][1]; // p2 is a pointer to an array of troll

p1 above IS NOT A POINTER TO AN ARRAY; p1 above IS A POINTER TO A TROLL;
p2 IS A POINTER TO AN ARRAY.

You can call me a troll and capitalise your bullshit as much as you like but
this doesn't change the fact that you're a proven idiot.
You have been proven incorrect already on this subject, ref thread: "You
snipped something".
 
G

Goran

My original question was:
Suppose I have the following code:
int (*p)[5] = (int (*)[5])new int[5];
How do I delete the allocated memory?
And my original answer was: you allocated an array of ints, you should
call delete[] on the pointer to the first element of that array, which
was returned from "new. Easy as a pie. That is, your code should be:
int *p = new int[5];
delete [] p;
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
No, All you said was that is was UB.

Not true.

This:

http://groups.google.com/group/comp.lang.c++/msg/b8ed179f99440d11

was my first response to your question.

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Yes and after I answered this you said the cast was UB.

My point was: it's not true that __all__ (emphasis added for better
reading comprehension) I said here was that your code had UB. I said
much more than that, and what you said was nonsense.
And thats what this
particular subthread has been about.

Not for me. For me, this thread was about you trying to pass
questionable-to-downright-unusable code as proof that a "pointer to T"
is somehow also a "pointer to array of T", and me trying to dissuade
you from that, with calm and rational thinking (as opposed to calling
people names, sending them insulting mails to their mailboxes and what
ever else that you did).

Goran.
 
P

Paul

My original question was:
Suppose I have the following code:
int (*p)[5] = (int (*)[5])new int[5];
How do I delete the allocated memory?
And my original answer was: you allocated an array of ints, you should
call delete[] on the pointer to the first element of that array, which
was returned from "new. Easy as a pie. That is, your code should be:
int *p = new int[5];
delete [] p;
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
No, All you said was that is was UB.

Not true.

This:

http://groups.google.com/group/comp.lang.c++/msg/b8ed179f99440d11

was my first response to your question.

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Yes and after I answered this you said the cast was UB.

My point was: it's not true that __all__ (emphasis added for better
reading comprehension) I said here was that your code had UB. I said
much more than that, and what you said was nonsense.
And thats what this
particular subthread has been about.

Not for me. For me, this thread was about you trying to pass
questionable-to-downright-unusable code as proof that a "pointer to T"
is somehow also a "pointer to array of T", and me trying to dissuade
you from that, with calm and rational thinking (as opposed to calling
people names, sending them insulting mails to their mailboxes and what
ever else that you did).

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

A pointer type, pointer to T *is* also a pointer to a to an array of T. I
don't need to prove it, its a fact of the language.
 
G

Goran

A pointer type, pointer to T *is* also a pointer to a to an array of T. I
don't need to prove it, its a fact of the language.

1.

int i;
int* pi = &i;

What array are we talking about here? In other words, if pi __is__ a
pointer to an array of T, then why is the above possible and correct,
even? Because C type system is broken or because your claim is broken?

2.

int a[3];
int (*pa)[3] = &a;

if p __is__ a pointer to array, what is pa? I believe language
disagrees with your claim here.

3.

int a[3];
int* p = a;

Here, we __commonly say__ that p is a pointer to array. But p is
__not__ a pointer to array. Instead, e.g. in "int (pa)[3] = &a;",
__pa__ is a pointer to array.

Your claim leads to confusion and errors, and is possibly the reason
why you want to write code such as that you've shown us here
(downright wrong, like Base/Derived example, very unsafe like
template<> foo example, and also at odds with what's prescribed, like
your very first example).

Goran.
 
P

Paul

A pointer type, pointer to T *is* also a pointer to a to an array of T. I
don't need to prove it, its a fact of the language.

1.

int i;
int* pi = &i;

What array are we talking about here? In other words, if pi __is__ a
pointer to an array of T, then why is the above possible and correct,
even? Because C type system is broken or because your claim is broken?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
The only thing broken is your brain. Obviously the above pointer doesn't
point to an array but the same type of pointer below points o an array:
int* p_to_array = new int[5];
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


2.

int a[3];
int (*pa)[3] = &a;

if p __is__ a pointer to array, what is pa? I believe language
disagrees with your claim here.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
pa is also a pointer to an array, its just a different type of pointer.
pa is the same type of pointer generally used to point to a 2d array. If pa
is dereferneced it returns a 1dim array, thus obeying the C++ language rules
for arrays.

Your use of the &addressof operator is simply creating a pointer that needs
to be dereferenced twice to access the array.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

3.

int a[3];
int* p = a;

Here, we __commonly say__ that p is a pointer to array. But p is
__not__ a pointer to array. Instead, e.g. in "int (pa)[3] = &a;",
__pa__ is a pointer to array.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
No p is a pointer to an array of 3 ints, that's why we commonly say .it's a
pointer to an array.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Your claim leads to confusion and errors, and is possibly the reason
why you want to write code such as that you've shown us here
(downright wrong, like Base/Derived example, very unsafe like
template<> foo example, and also at odds with what's prescribed, like
your very first example).
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You certainly seem confused, I'm not.

A pointer to a 1d array is dereferenced once to return an element:
p_arr_1d[0];

A pointer to a 2d array is dereferneced twice to return an element:
p_arr_2d[0][0];

With your theory you think a pointer to a 1d array is like so :
int (*p)[5] = &a_1d_array;
All this does it make a pointer which has another level of indircetion and
would unneccessarily need to be dereferenced twice to access the array.
(*p)[0];

You, and many others, are obviously unable to garsp the simple facts of how
pointers to arrays work in C++ . For this reason and many other unreasonable
arguments I have seen in these forums , I am going to try and stop reading
this shit and eventually I will have fully plonked this well and trully
disgusting newsgroup that is full of arseholes know-it-alls who don't have a
clue, but they actually think they are expert programmers.
Clueless arseholes with no personailty, only bad personality, and too much
time to spend reading documents they dont understand.

Just look at your point 1 to see how much of an unreasonable idiotic
arsehole you are. What goes through your idiot brain?


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 
B

boltar2003

Just look at your point 1 to see how much of an unreasonable idiotic
arsehole you are. What goes through your idiot brain?

Seems to me a classic case of what happens when someone who's learnt high
level C++ or Java is now trying to learn the low level C part of the language.
I've seen it time and time again. A very good reason why anyone who interviews
for a C++ job interview should also be interviewed to test their C knowledge
too since if they don't understand pointers, arrays, pointer arithmetic and
the like there's a good chance they'll eventually mess something up badly.

B2003
 
G

Goran

A pointer type, pointer to T *is* also a pointer to a to an array of T.I
don't need to prove it, its a fact of the language.

1.

int i;
int* pi = &i;

What array are we talking about here? In other words, if pi __is__ a
pointer to an array of T, then why is the above possible and correct,
even? Because C type system is broken or because your claim is broken?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
The only thing broken is your brain. Obviously the above pointer doesn't
point to an array but the same type of pointer below points o an array:
int* p_to_array = new int[5];
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

No, it points to the first element of array allocated by new int[5].

But OK, I see what is your problem: you don't understand the
difference between __is__ and __points to__. That's what's confusing
you. No biggie, I can explain that to you. Consider:

class A {};
class B : public A {};

A a;
B b;
A* p=&a; // p __is__ a pointer to A and it points to an A.
p = &b; // p __is__ a pointer to A, but it points to a B.

The above is an example of a pointer that __is__ one thing (a pointer
to an A), but can __point to__ two different types. Types related, but
different nonetheless. See, there's a difference between __is__ and
__points to__? Relevant one at that, too.

Consider also:

TYPE* p; int i; int a[2]; int* p1=i; int* p2=a;

Now... Expression (*p) is of type T&. Expression (p->) is also of type
T&. That much is clear. Same for p1.

But what about p2? Following your claim and basic logic, it's int[2]&,
which is, of course, utter nonsense.

Goran.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top