Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

delete[] p or delete[] *p

57 views
Skip to first unread message

Paul

unread,
Mar 27, 2011, 12:34:51 AM3/27/11
to
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??

cg_chas

unread,
Mar 27, 2011, 1:19:37 AM3/27/11
to

You have casted the pointer type returned from new into a different pointer, but
regardless, new allocated an array of 5 ints, so you call delete [] on the
pointer that new returned.

delete [] reinterpret_cast<int*>(p);


cg_chas

unread,
Mar 27, 2011, 1:21:19 AM3/27/11
to

my correction: should say you have casted the pointer type returned from new
into a different pointer "type"

Joshua Maurice

unread,
Mar 27, 2011, 5:36:18 AM3/27/11
to
On Mar 26, 10:21 pm, cg_chas <cg_c...@hotmail.com> wrote:
> On Sun, 27 Mar 2011 01:19:37 -0400, cg_chas <cg_c...@hotmail.com> wrote:

> >On Sun, 27 Mar 2011 05:34:51 +0100, "Paul" <pchris...@yahoo.co.uk> wrote:
>
> >>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??
>
> >You have casted the pointer type returned from new into a different pointer, but
> >regardless, new allocated an array of 5 ints, so you call delete [] on the
> >pointer that new returned.
>
> my correction: should say  you have casted the pointer type returned from new
> into a different pointer "type"

I'd like to point out that AFAIK the first cast may result in a loss
of information. You're only guaranteed round-way trips through void*,
char*, and unsigned char*, (and an integer type of sufficient size).
Thus the delete[] could be UB on a conforming platform. That's right,
right?

io_x

unread,
Mar 27, 2011, 6:11:14 AM3/27/11
to

"Paul" <> ha scritto nel messaggio

i not use delete-new i use always malloc()-free()
or my version of these functions

Öö Tiib

unread,
Mar 27, 2011, 10:06:25 AM3/27/11
to

I think that c) but why you reinterpret_cast at first place?

I start to wonder do you ever use raw dynamic arrays and if then why
do you use them? I don't. In C code I do but there are allocated with
malloc() and deallocated with free(). Usage of "delete[]" itself
usually indicates that some novice in team has copy-pasted something
cheesy from google or from a book into our code base.

In C++ it is often clear how a particular container of T's should be
used (as stack or as set or as queue or as vector). Sometimes it is
unclear. I usually take std::vector<T> first when it is unsure how
container will be used. Later it settles and usually it remains as
such for ages after.

Sometimes very rarely it later becomes apparent that a container
causes performance or maintainability issues related to nature or
usage of it. Then i revisit what exact underlying container type is
used. Refactoring vector into some other container may make sense at
that spot.

The chosen type depends on what is done with container and what is not
done with it. There are so lot of somewhat similar to vector
containers to choose. boost::array<T>, boost::scoped_array<T>,
std::map<int,T>, std::list<T>, boost::intrusive::slist<T> and so on.
Basically ... just describe exact nature and usage of container and no
doubt that there is very close template available and free to use.
Vector may become even raw static array, but i see no reasons to use
raw dynamic array in C++.

Raw static arrays i use for static tables. Sometimes initial
requirements described some "list" of information and vector was
chosen and later it did appear that it is actually static table of
information. There is so elegant (IMHO) syntax for initializing static
arrays in C so it is lot better to maintain. Like i understand C++0x
will allow using such syntax for initializing other containers as
well.

Kai-Uwe Bux

unread,
Mar 27, 2011, 10:32:45 AM3/27/11
to
Joshua Maurice wrote:

That depends on:

a) which cast is used and
b) what the alignment requirement for the involved types are.

According to [5.2.10/7] you can reinterpret_cast round trip from T1* to T2*
and back provided the alignment of T2 are not stricter than the ones for T1.

To me, the C-style cast within the expression

(int (*)[5]) new int[5]

looks like a reinterpret_cast. Thus, [5.2.10/7] applies. As to whether
int[5] may have stricter alignment requirements than int, I think the
standard remains silent.


Best,

Kai-Uwe Bux

Paul

unread,
Mar 27, 2011, 12:39:08 PM3/27/11
to

>"嘱 Tiib" <oot...@hot.ee> wrote in message
>news:f8e26e9c-2799-420f...@f2g2000yqf.googlegroups.com...

>On Mar 27, 7:34 am, "Paul" <pchris...@yahoo.co.uk> wrote:
>> 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??
>
>I think that c) but why you reinterpret_cast at first place?
>
To convert the dynamic array into an array object type, that would decay
into a pointer that carried size information, for example:

template<typename T, int S, typename U= T (&)[S]>
class R{
public:
R():pp((int (*)[S])new int[S+1]), r(*(pp+1)){r[-1]=S;}
U getArray(){return r;}
void delete_it(){ delete[] (int*)pp; }
private:
int (*pp)[S];
T (&r)[S];
};

template<typename T>
void foo(T r){
std::cout<<"size of array:\t" << r[-1];
std::cout<< "\ntype of array:\t" << typeid(T).name();
}

int main() {
R<int, 7> r;
int (&r1)[7] = r.getArray();
foo(r.getArray());
std::cout<<"\ntype of r1:\t"<< typeid(r1).name();

r.delete_it();
}

>I start to wonder do you ever use raw dynamic arrays and if then why
>do you use them? I don't. In C code I do but there are allocated with
>malloc() and deallocated with free(). Usage of "delete[]" itself
>usually indicates that some novice in team has copy-pasted something
>cheesy from google or from a book into our code base.

OFC dynamic arrays are very usefull , especially if creating a specialised
container.

>In C++ it is often clear how a particular container of T's should be
>used (as stack or as set or as queue or as vector). Sometimes it is
>unclear. I usually take std::vector<T> first when it is unsure how
>container will be used. Later it settles and usually it remains as
>such for ages after.

std::vector is not always the best solution for use within specialised class
designs. I don't see std::vector as a replacement for dynamic arrays, its a
good quick and easy solution if you need a basic resizeable vector with safe
some built in safety.

>Sometimes very rarely it later becomes apparent that a container
>causes performance or maintainability issues related to nature or
>usage of it. Then i revisit what exact underlying container type is
>used. Refactoring vector into some other container may make sense at
>that spot.

I think in C++ we have the power to create a wide variety of specialised
types, data records etc. I don't like to think that there is a certain
limited amount of types, defined by the std lib , that we should use.

>The chosen type depends on what is done with container and what is not
>done with it. There are so lot of somewhat similar to vector
>containers to choose. boost::array<T>, boost::scoped_array<T>,
>std::map<int,T>, std::list<T>, boost::intrusive::slist<T> and so on.
>Basically ... just describe exact nature and usage of container and no
>doubt that there is very close template available and free to use.
>Vector may become even raw static array, but i see no reasons to use
>raw dynamic array in C++.

I prefer to design my own type for a spefic need, if there is a something
suitable in the std lib then great I will use it. but often they are just
not perfectly suited to the job.


>Raw static arrays i use for static tables. Sometimes initial
>requirements described some "list" of information and vector was
>chosen and later it did appear that it is actually static table of
>information. There is so elegant (IMHO) syntax for initializing static
>arrays in C so it is lot better to maintain. Like i understand C++0x
>will allow using such syntax for initializing other containers as
>well.

You are probably basing your views on personal experience as many of us do.
One of the major attractions to C++ , for me , is the ability to easily
create specialised types whereas assembly its a bit more complex, I like to
use this feature of the language often , and I get much satisfaction from
doing so.
As you may have guessed I am no big fan of the std lib, I do like some of
the template features but generally I don't bother with it unless it suits
the job perfectly.
AFAIK boost multi-array, and I don't think this is part of the std lib, is
the closest thing to my needs and its a bit overkill tbh.

Also learning about different ways of allocating memory is usefull for
learning purposes and enhances your programming skills, sometimes I prefer
to invoke the OS's API directly for memory allocation simply to become more
familiar with the API.

HTH
Paul.

Vidar Hasfjord

unread,
Mar 27, 2011, 2:58:03 PM3/27/11
to
On Mar 27, 5:34 am, "Paul" <pchris...@yahoo.co.uk> wrote:
> [Suppose I have the following code:

>
> int (*p)[5] = (int (*)[5])new int[5];
>
> How do I delete the allocated memory?

As your question has been answered elsewhere, I'll just add an
interesting aside from a language design perspective. If C++ had a
more regular design the type of the "new int [5]" expression would not
degenerate to "int*". A regular design would render the array
overloads of new and delete superfluous, and make your cast here
unnecessary. Consider the irregularity of:

typedef struct {int a, b, c, d, e;} Struct; // aggregate type
typedef int Array [5]; // aggregate type
Struct* ps = new Struct; // Ok!
Array* pa = new Array; // Error! Should be "int* pa".
delete ps; // Ok!
delete pa; // Error! Should be "delete [] pa".

If instead C++ was regular and this was correct code, the type of the
pointer would carry the size information and allow the regular delete
operator to release the correct amount of memory. These irregularities
are avoided by std::array:

typedef std::array <int, 5> Array; // aggregate type
Array* pa = new Array; // Ok!
delete pa; // Ok!

Dereferencing the pointer, (*pa), gives you a reference (lvalue) to
the array as a whole, and an indexing operator is implemented for the
array class itself (not via degeneration into pointer arithmetic).

The new std::array circumvents the numerous irregularities between
pointers and arrays that causes so much confusion. I.e. you can copy
arrays, pass and return arrays by value to and from functions, and the
array will never implicitly convert to a pointer to the first element.
Hence I recommend its use instead of C-style arrays.

Regards,
Vidar Hasfjord

Goran

unread,
Mar 28, 2011, 4:51:10 AM3/28/11
to

d) when you allocate memory using new T[], you use delete [], passing
it a T* returned to you by a prior cal to "new T[]". This is how new/
delete are supposed to work. You broke that with your casts, which is
the original sin of this code.

I would guess that all of a, b, and c will work on many
implementations, but I know of no guarantee for that. One can imagine
an implementation with bounds-checking where such code fails badly.

Your "R" example further down makes little sense, perhaps you should
have given it a bit more of thought. (E.g. what's with r[-1] = S, that
requires that T has operator=(int) or something, and S is a compile-
time constant anyhow!?)

Did you mean to create a variant of the old C trick with size,
followed by an array of struct, where size is a run-time value? There
was a +/- heated discussion some time ago about this here, somebody
made one half-decent C++ implementation then. (No conversion to an
array though, that wasn't the discussion's goal).

Goran.

SG

unread,
Mar 28, 2011, 7:25:49 AM3/28/11
to
On 27 Mrz., 20:58, Vidar Hasfjord wrote:
> [...]

> unnecessary. Consider the irregularity of:
>
>   typedef struct {int a, b, c, d, e;} Struct; // aggregate type
>   typedef int Array [5]; // aggregate type
>   Struct* ps = new Struct; // Ok!
>   Array* pa = new Array; // Error! Should be "int* pa".
>   delete ps; // Ok!
>   delete pa; // Error! Should be "delete [] pa".
>
> If instead C++ was regular and this was correct code, the type of the
> pointer would carry the size information and allow the regular delete
> operator to release the correct amount of memory.

For the size to be part of the pointer _type_ this size must be a
compile-time constant. But new[] does not require a compie-time
constant for the number of elements:

void foo(int x) {
new int[x]; // x is not a compile-time constant
}

So, the current new[] operator can do something that you can't emulate
with "new array<T,N>" properly.

Perhaps an alternate syntax would have been better and more regular:

void foo(int x)
{
int *p = new[x] int; // not real C++ code (unfortunately)
delete[] p;

int (*q)[5] = new int[5]; // not real C++ code (unfortunately)
delete q;
}

Anyhow, I consider new[]/delete[] and raw arrays to be nearly useless.
We have better alternatives and soon get some more: vector<T>,
array<T,N>, unique_ptr<array<T,N>>, for example. So, "fixing" arrays
and new[] w.r.t. regularity wouldn't buy you much. You'd mainly lose
compatibility with old code.

my 2 cents,
SG

Vidar Hasfjord

unread,
Mar 28, 2011, 9:29:18 AM3/28/11
to
On Mar 28, 12:25 pm, SG <s.gesem...@gmail.com> wrote:
> For the size to be part of the pointer _type_ this size must be a
> compile-time constant. But new[] does not require a compie-time
> constant for the number of elements: [...]

Good point. But, if C++ was regular it would require the size to be a
compile-time constant; as it does everywhere else in the language
where an array type is expressed. I.e. the argument to new would
simply be a regular type expression.

The unrelated use of square brackets to specify a run-time argument is
highly irregular. And, more over, with templates in the language it is
unnecessary. Dynamic allocation can be implemented as a library
function. All you need is a low-level memory allocation function
(malloc) and placement-new (or a similar construct to allow you to
construct an object in allocated memory). E.g.

template <class T> T* construct (size_t n = 1); // replaces new
template <class T> void destruct (T*); // replaces delete

> Anyhow, I consider new[]/delete[] and raw arrays to be nearly useless.
> We have better alternatives and soon get some more: vector<T>,
> array<T,N>, unique_ptr<array<T,N>>, for example.

Agree. C++ programmers, except those dealing with legacy code or
implementing the standard library, can now avoid these irregularities.

Regards,
Vidar Hasfjord

Michael Doubez

unread,
Mar 28, 2011, 10:27:53 AM3/28/11
to
On 28 mar, 15:29, Vidar Hasfjord <vattilah-gro...@yahoo.co.uk> wrote:
> On Mar 28, 12:25 pm, SG <s.gesem...@gmail.com> wrote:
>
> > For the size to be part of the pointer _type_ this size must be a
> > compile-time constant. But new[] does not require a compie-time
> > constant for the number of elements: [...]
>
> Good point. But, if C++ was regular it would require the size to be a
> compile-time constant; as it does everywhere else in the language
> where an array type is expressed. I.e. the argument to new would
> simply be a regular type expression.
>
> The unrelated use of square brackets to specify a run-time argument is
> highly irregular.

This seems contradictory, the irregularity of array with runtime size
is AFAIS intended for providing a regular type expression syntax to
use with new operator.

> And, more over, with templates in the language it is
> unnecessary. Dynamic allocation can be implemented as a library
> function. All you need is a low-level memory allocation function
> (malloc) and placement-new (or a similar construct to allow you to
> construct an object in allocated memory). E.g.
>
>   template <class T> T* construct (size_t n = 1); // replaces new
>   template <class T> void destruct (T*); // replaces delete

And how do you handle constructor parameters for non-array
initialisation ?
For a workable solution, you would need perfect forwarding which isn't
yet standard.

Moreover, this means that unless you standardise it, every project
would have it's own syntax for allocation class-objects; if you
standardize it, why not make it an operator with a nice syntax.

> > Anyhow, I consider new[]/delete[] and raw arrays to be nearly useless.
> > We have better alternatives and soon get some more: vector<T>,
> > array<T,N>, unique_ptr<array<T,N>>, for example.
>
> Agree. C++ programmers, except those dealing with legacy code or
> implementing the standard library, can now avoid these irregularities.

Then, how do you implement a dynamic length array of non-copiable
objects ?

--
Michael

Öö Tiib

unread,
Mar 28, 2011, 11:18:35 AM3/28/11
to

Neither copyable nor movable? One may consider either
boost::scoped_array<T> or std::vector<unique_ptr<T>> depending on
other constraints.

A

unread,
Mar 28, 2011, 11:57:34 AM3/28/11
to
> Suppose I have the following code:
> int (*p)[5] = (int (*)[5])new int[5];
> How do I delete the allocated memory?

start using std::vector (or some other container) instead and forget about
manual memory management. leave it to compiler. you'll have much less memory
leaks.
since i started using stl i forgot about how stupid all that manual handling
of pointers and arrays used to be.

look how simpler it is:

// init
std::vector<int*> p(5);

// automatically deleted when it loses scope


Noah Roberts

unread,
Mar 28, 2011, 1:17:44 PM3/28/11
to

Both statements are correct. What you actually need to correct is,
"...so you call delete [] on the pointer that new returned," to, "...so
you call delete [] on the same pointer type that new returned." Key
point here is that casting creates new objects.

--
http://crazycpp.wordpress.com

Paul

unread,
Mar 28, 2011, 1:37:50 PM3/28/11
to

"Vidar Hasfjord" <vattila...@yahoo.co.uk> wrote in message
news:80d512c9-799d-445d-bd99->58c30a...@l11g2000yqb.googlegroups.com...

>On Mar 27, 5:34 am, "Paul" <pchris...@yahoo.co.uk> wrote:
>> [Suppose I have the following code:
>>
>> int (*p)[5] = (int (*)[5])new int[5];
>>
>> How do I delete the allocated memory?

>As your question has been answered elsewhere, I'll just add an
>interesting aside from a language design perspective. If C++ had a
>more regular design the type of the "new int [5]" expression would not
>degenerate to "int*". A regular design would render the array
>overloads of new and delete superfluous, and make your cast here
>unnecessary. Consider the irregularity of:

I don't think my question has bene answered, what I was asking was the
difference between each delete invocation, it seems that each is identical
but I get warning for delete *p, see code:

class Base{
public:
Base() {std::cout<<"Constructing base\n";}
~Base(){std::cout<<"Destructing base\n";}
};

int main() {
Base (*pA)[4] = (Base (*)[4])new Base[4];
Base* pB = new Base[3];

std::cout<<"\nDeleting pA:\n";
delete[] pA;
//delete[] *pA;
std::cout<<"\nDeleting pB:\n";
delete[] pB;


If you run the above code you see that each invocation of delete[] produces
the desired effect, even if you use *pA instead of pA. This however gives a
warning but I think the array is converted to a pointer. I did my tests on a
windows platform but it may not be the same on other platforms.
This suggests to me that the pointer-type is not rellevant, on my platform
at least, when calling delete[].

> typedef struct {int a, b, c, d, e;} Struct; // aggregate type
> typedef int Array [5]; // aggregate type
> Struct* ps = new Struct; // Ok!
> Array* pa = new Array; // Error! Should be "int* pa".
> delete ps; // Ok!
> delete pa; // Error! Should be "delete [] pa".

>If instead C++ was regular and this was correct code, the type of the
>pointer would carry the size information and allow the regular delete
>operator to release the correct amount of memory. These irregularities
>are avoided by std::array:

Yeah but it's never going to be a regular language, that is not the nature
of comp programming. All you can do is wrap it up in some class and make it
apper like regular syntax. I'm no big fan of unnecessary wrapping.

> typedef std::array <int, 5> Array; // aggregate type
> Array* pa = new Array; // Ok!
> delete pa; // Ok!

Yes but look at all the extra code you need to introduce behind the scenes
to get these semantics. I don't see any advantage in using an STL class over
a pointer in many cases, there are some cases where they are perfect and
really good , but not always.

>Dereferencing the pointer, (*pa), gives you a reference (lvalue) to
>the array as a whole, and an indexing operator is implemented for the
>array class itself (not via degeneration into pointer arithmetic).

Thats simple to achieve without the introduction of a STL class, for
example:

int (*pA)[6] = (int (*)[6])new int[6];
int (&rA)[6] = *pA;

The only advantage I see for using STL vectors is that they are expandable.
If you need a quick fix generic expandable array I agree they are the
solution. But for a simple fixed size array I wouldn't bother with an STL
class.

>The new std::array circumvents the numerous irregularities between
>pointers and arrays that causes so much confusion. I.e. you can copy
>arrays, pass and return arrays by value to and from functions, and the
>array will never implicitly convert to a pointer to the first element.
>Hence I recommend its use instead of C-style arrays.

I've never really used it TBH, my compiler setup doesn't seem to have that
library.
I don't really see the need for it in most cases, I'm quite happy with
normal C++ arrays, I'm just a bit rusty on C++ so I was trying to confirm
the behaviour of delete[] with the given cases.
TY for your post
Paul.

Vidar Hasfjord

unread,
Mar 28, 2011, 3:22:25 PM3/28/11
to
On Mar 28, 6:37 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> This suggests to me that the pointer-type is not rellevant, on my platform
> at least, when calling delete[].

While it may not make a difference in this particular example, in
general it is very much relevant. The correct type is needed for
delete to call the correct destructor. Also note that both "delete"
and "delete[]" can be overloaded globally and per class, in which case
the correct type is needed to select the correct overload.

Regards,
Vidar Hasfjord

Kai-Uwe Bux

unread,
Mar 28, 2011, 2:33:23 PM3/28/11
to
Paul wrote:

[...]

The above seems to be rather roundabout. Also, the templates indicate a
generality that is not really there: if you try to instantiate R<long,7> the
code will not compile. Furthermore, I do not understand why you would want
to store size information within the array when it is available through the
type system: after all, the array size is passed as a template parameter
whence it must be a compile time constant. Finally, the casting could invoke
undefined behavior as soon as you access array elements (any use other than
casting back is undefined, I think).

For comparison look at the free functions new_it<> and delete_it<>. To me,
it seems, that they do the same as the above class R<> except that the size
is not required to be a compile time constant. (Also, now the templates work
for types T!=int.)

#include <iostream>
#include <ostream>
#include <typeinfo>


template<typename T, int S, typename U= T (&)[S]>
class R{
public:
R():pp((int (*)[S])new int[S+1]), r(*(pp+1)){r[-1]=S;}
U getArray(){return r;}
void delete_it(){ delete[] (int*)pp; }
private:
int (*pp)[S];
T (&r)[S];
};

template < typename IntegerType >
IntegerType * new_it ( int size ) {
IntegerType * ptr = new IntegerType [size+1];
ptr[0] = size;
return ( ptr+1 );
}

template < typename IntegerType >
void delete_it ( IntegerType * ptr ) {
delete ( ptr-1 );
}

template<typename T>
void foo(T r){
std::cout<<"size of array:\t" << r[-1];
std::cout<< "\ntype of array:\t" << typeid(T).name();
}

int main() {
{
R<int, 7> r; // try R<long,7> here.


int (&r1)[7] = r.getArray();
foo(r.getArray());
std::cout<<"\ntype of r1:\t"<< typeid(r1).name();
r.delete_it();
}

{
std::cout << "\n";
int * ptr = new_it<int>(7); // try long * ptr = new_it<long>(7) here;
foo(ptr);
delete_it( ptr );
std::cout << "\n";
}
}


Best

Kai-Uwe Bux

Paul

unread,
Mar 28, 2011, 4:12:52 PM3/28/11
to

"Kai-Uwe Bux" <jkher...@gmx.net> wrote in message
news:imqo3l$l45$1...@hoshi.visyn.net...
Yes there are lots of ways to do it , the code was just a example..
TY
Paul.

Paul

unread,
Mar 28, 2011, 4:26:40 PM3/28/11
to

"Vidar Hasfjord" <vattila...@yahoo.co.uk> wrote in message
news:35e223bd-251f-4697-aa66->6809d0...@w7g2000yqe.googlegroups.com...

I'm not talking about pointer-types , in general. I'm talking about pointer
to arrays and pointer to array-object types as in:
int* or int(*)[size];
Base* or Base (*)[size]
etc etc.

If I call delete[] on int*, it's no different to int (*)[size]? Or is it?
How does the compiler know how many destructors to call?
And what if call delete[] *(int (*)[size])? Is it implicitly converted to
int*?

cg_chas

unread,
Mar 28, 2011, 4:30:27 PM3/28/11
to
On Mon, 28 Mar 2011 18:37:50 +0100, "Paul" <pchr...@yahoo.co.uk> wrote:

>
>"Vidar Hasfjord" <vattila...@yahoo.co.uk> wrote in message
>news:80d512c9-799d-445d-bd99->58c30a...@l11g2000yqb.googlegroups.com...
>>On Mar 27, 5:34 am, "Paul" <pchris...@yahoo.co.uk> wrote:
>>> [Suppose I have the following code:
>>>
>>> int (*p)[5] = (int (*)[5])new int[5];
>>>
>>> How do I delete the allocated memory?
>
>>As your question has been answered elsewhere, I'll just add an
>>interesting aside from a language design perspective. If C++ had a
>>more regular design the type of the "new int [5]" expression would not
>>degenerate to "int*". A regular design would render the array
>>overloads of new and delete superfluous, and make your cast here
>>unnecessary. Consider the irregularity of:
>
>I don't think my question has bene answered, what I was asking was the
>difference between each delete invocation, it seems that each is identical

It is an issue of type as Vidar points and myself have pointed out. The only
thing that your three choices from the OP have in common is that the address
stored by the pointer is the same. Not to re-open a whole can of worms, but had
you walked away from the previous seven threads that you started in agreement
with those that replied, you would not be confused on this point.

I don't think that's what he means when he says regular language, but anyway, I
think it is more of an issue of backwards compatibility with C than simply the
nature of programming in general.

>
>> typedef std::array <int, 5> Array; // aggregate type
>> Array* pa = new Array; // Ok!
>> delete pa; // Ok!
>
>Yes but look at all the extra code you need to introduce behind the scenes
>to get these semantics. I don't see any advantage in using an STL class over
>a pointer in many cases, there are some cases where they are perfect and
>really good , but not always.

I see several advantages, even for many simple cases. See below.

>
>>Dereferencing the pointer, (*pa), gives you a reference (lvalue) to
>>the array as a whole, and an indexing operator is implemented for the
>>array class itself (not via degeneration into pointer arithmetic).
>
>Thats simple to achieve without the introduction of a STL class, for
>example:
>
>int (*pA)[6] = (int (*)[6])new int[6];
>int (&rA)[6] = *pA;
>
>The only advantage I see for using STL vectors is that they are expandable.
>If you need a quick fix generic expandable array I agree they are the
>solution. But for a simple fixed size array I wouldn't bother with an STL
>class.

std::vector gives you size management, memory management, and a set of
guarantees with regards to behavior. Because it is an STL container, you can
define custom allocators as well as use the class iterators to access the
container or perform standard algorithms on the container data. Keep in mind
that std::vector is the "quintessential generic" general purpose container.
Other containers give you a variety of other standardized behaviors and
functionality. Even for a fixed array, std::vector's type safety and
interoperability with the other C++ built in class types make it a worthy
consideration.

For me personally, only for the case of lookup tables of constants or tables of
data that does not change do I generally prefer raw arrays over STL containers.

>>The new std::array circumvents the numerous irregularities between
>>pointers and arrays that causes so much confusion. I.e. you can copy
>>arrays, pass and return arrays by value to and from functions, and the
>>array will never implicitly convert to a pointer to the first element.
>>Hence I recommend its use instead of C-style arrays.
>
>I've never really used it TBH, my compiler setup doesn't seem to have that
>library.
>I don't really see the need for it in most cases, I'm quite happy with
>normal C++ arrays, I'm just a bit rusty on C++ so I was trying to confirm
>the behaviour of delete[] with the given cases.
>TY for your post
>Paul.

Just as a side note and a bit off-topic (but not entirely out of context)
consider the benefits of a smart pointer class over using raw pointers in
general. As cases become more complex, such as with COM, for example, you stand
to benefit greatly from not having to manage things such as reference counts,
pointer validitiy, and internal allocation.

cg_chas

unread,
Mar 28, 2011, 4:39:45 PM3/28/11
to
On Mon, 28 Mar 2011 21:26:40 +0100, "Paul" <pchr...@yahoo.co.uk> wrote:

>
>"Vidar Hasfjord" <vattila...@yahoo.co.uk> wrote in message
>news:35e223bd-251f-4697-aa66->6809d0...@w7g2000yqe.googlegroups.com...
>>On Mar 28, 6:37 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
>>> This suggests to me that the pointer-type is not rellevant, on my
>>> platform
>>> at least, when calling delete[].
>
>>While it may not make a difference in this particular example, in
>>general it is very much relevant. The correct type is needed for
>>delete to call the correct destructor. Also note that both "delete"
>>and "delete[]" can be overloaded globally and per class, in which case
>>the correct type is needed to select the correct overload.
>
>I'm not talking about pointer-types , in general. I'm talking about pointer
>to arrays and pointer to array-object types as in:
>int* or int(*)[size];
>Base* or Base (*)[size]
>etc etc.

Then yes, you are in fact talking about pointer types. I knew that this thread
inevitably was going to come to this. It was just a matter of time as the
preceding seven Paul discussion threads have shown.

cg_chas

unread,
Mar 28, 2011, 4:44:48 PM3/28/11
to

agreed.

Vidar Hasfjord

unread,
Mar 28, 2011, 5:52:42 PM3/28/11
to
On Mar 28, 3:27 pm, Michael Doubez <michael.dou...@free.fr> wrote:
> This seems contradictory, the irregularity of array with runtime size
> is AFAIS intended for providing a regular type expression syntax to
> use with new operator.

Granted, you can say a similarity of syntax is regularity, but the
semantic irregularity it causes is high, and it was the semantic
irregularities I alluded to here. I view it as undesirable that the
type-id syntax has been reused to specify a run-time parameter.

> > template <class T> T* construct (size_t n = 1); // replaces new
> > template <class T> void destruct (T*); // replaces delete
>
> And how do you handle constructor parameters for non-array
> initialisation ?
> For a workable solution, you would need perfect forwarding which isn't
> yet standard.

Sorry, these were meant to replace just "new[]" and "delete[]",
leaving "new" and "delete" as before, but with regular semantics.
Perfect forwarding would make it feasable to also replace "new" and
"delete", although the language would still need placement-new, or
something similar, to construct objects in allocated memory.

> Moreover, this means that unless you standardise it, every project
> would have it's own syntax for allocation class-objects; if you
> standardize it, why not make it an operator with a nice syntax.

I'm just hypothesising about a regular subset of C++ here, but yes,
you may assume it would have the necessary features in the language
and support in the library. But I don't see how an operator can be
much nicer than template syntax. This is the road we're on, anyway (C+
+0x):

auto pa = make_shared <A> (...); // Create A, return shared_ptr.

Regards,
Vidar Hasfjord

Vidar Hasfjord

unread,
Mar 28, 2011, 7:27:49 PM3/28/11
to
On Mar 28, 9:26 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> If I call delete[] on int*, it's no different to int (*)[size]? Or is it?

You may have to consult the C++ standard to see if it gives any
guarantees. Despite your casts, "int*" is what "new" returned, so that
seems the only sure thing. Maybe allowing "int (*)[size]" is a
concession from the compiler for having decayed the type in the first
place? :-)

> How does the compiler know how many destructors to call?

See:
http://www.parashift.com/c%2B%2B-faq-lite/freestore-mgmt.html#faq-16.14

> delete[] *(int (*)[size])? Is it implicitly converted to int*?

Yes, and Visual C++ 2010 also produces a warning in this case (warning
C4154: deletion of an array expression; conversion to pointer
supplied).

Regards,
Vidar Hasfjord

Paul

unread,
Mar 28, 2011, 7:55:40 PM3/28/11
to

"Vidar Hasfjord" <vattila...@yahoo.co.uk> wrote in message
news:c4e51965-d6a8-40ce...@d28g2000yqf.googlegroups.com...

> On Mar 28, 9:26 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
>> If I call delete[] on int*, it's no different to int (*)[size]? Or is it?
>
> You may have to consult the C++ standard to see if it gives any
> guarantees. Despite your casts, "int*" is what "new" returned, so that
> seems the only sure thing. Maybe allowing "int (*)[size]" is a
> concession from the compiler for having decayed the type in the first
> place? :-)
>
>> How does the compiler know how many destructors to call?
>
> See:
> http://www.parashift.com/c%2B%2B-faq-lite/freestore-mgmt.html#faq-16.14

Yes I already knew about these techniques.
What my concern was that with delete [] called on int (*)[size] type
pointer...
C++ would call the destructor for the 1st element, then move
size*sizeof(int), that is sizeof( *(int (*)[size]) ) to look for the second
element. As oppose to moving only sizeof(int) per element, in the case of
delete[] int*
. Therefore I would be freeing more memory than I allocated, but this
doesn't seen to happen

>
>> delete[] *(int (*)[size])? Is it implicitly converted to int*?
>
> Yes, and Visual C++ 2010 also produces a warning in this case (warning
> C4154: deletion of an array expression; conversion to pointer
> supplied).
>

Ah nice that confirms that , for VC++ at least.
Ty again for your post.

Goran

unread,
Mar 29, 2011, 4:32:51 AM3/29/11
to
On Mar 28, 10:26 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> If I call delete[] on int*, it's no different to int (*)[size]? Or is it?

You are repeatedly trying to get into UB land. You should __not__ ask
the question you are asking. You never allocated int (*)[size]. Can't
do that, perhaps because of array type erasure: as soon as the array
type hits operator new, array type is erased and new sees a pointer (a
double one, "**", but nonetheless). You never got an __array__ out of
new, and you can't pass an array to delete.

If you have TYPE* that you need to delete, you must know how you
allocated it, end of. If you did p = new TYPE(), you do delete p; if
you did p = new TYPE[1], you do delete [] p; (yes, even if you put 1
in []). If you did p = new TYPE(*)[1], you do delete [] p (but, p's
type is TYPE**).

> How does the compiler know how many destructors to call?

Not ours to know (hint: implementation's heap management internals
serve for that).

> And what if call delete[] *(int (*)[size])? Is it implicitly converted to
> int*?

I'd wager yes, due to array-type-erasure. But you did not __allocate__
that, now did you? (That is, you have some other problem in your code,
so this question should not be asked in the first place).

Goran.

Paul

unread,
Mar 29, 2011, 7:07:49 AM3/29/11
to

"Goran" <goran...@gmail.com> wrote in message
news:984871da-0be5-494c-8a7f->910aad...@j35g2000prb.googlegroups.com...

>On Mar 28, 10:26 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
>> If I call delete[] on int*, it's no different to int (*)[size]? Or is it?
>
>You are repeatedly trying to get into UB land. You should __not__ ask
>the question you are asking. You never allocated int (*)[size]. Can't
>do that, perhaps because of array type erasure: as soon as the array
>type hits operator new, array type is erased and new sees a pointer (a
>double one, "**", but nonetheless). You never got an __array__ out of
>new, and you can't pass an array to delete.
What do you mean the array-type hits operator new its array-type is erased?
There never is an array-type the C runtime will return a pointer to int, not
some array-object-type.


>If you have TYPE* that you need to delete, you must know how you
>allocated it, end of. If you did p = new TYPE(), you do delete p; if
>you did p = new TYPE[1], you do delete [] p; (yes, even if you put 1
>in []). If you did p = new TYPE(*)[1], you do delete [] p (but, p's
>type is TYPE**).

The type is the same , both int type arrays, only the level of dereference
is different for example:

int (*p1)[5] = (int (*)[5])new int*[5]; /*2d array*/
int (*p2)[5] = (int (*)[5])new int[5]; /*1d array*/
int (*p3)[5] = new int[5][5]; /*2d array*/
delete[] p1;
delete[] p2;
delete[] p3;

What is the difference with the above deletes?


>
>> How does the compiler know how many destructors to call?
>
>Not ours to know (hint: implementation's heap management internals
>serve for that).

>> And what if call delete[] *(int (*)[size])? Is it implicitly converted to
>> int*?

>I'd wager yes, due to array-type-erasure. But you did not __allocate__
>that, now did you? (That is, you have some other problem in your code,
>so this question should not be asked in the first place).

I don't know this term "array type erasure". What do you mean by that?


cg_chas

unread,
Mar 29, 2011, 12:24:22 PM3/29/11
to

An inane question since the case itself is inane. Not to mention this has been
asked and answered more than once.

What you should be concerned with asking yourself is why you are casting the
pointer types returned by new into a different types without at least first
storing the uncasted returned type .

Each of the above new expressions returns a different type of pointer. As others
have said more than once, it is a bad idea to cast the type of new's return and
then call delete [] on it because it opens the door to UB for every case where
new's return type does not match the type of pointer you pass to delete [].

In case it has not been said, allocating multidimensional arrays with new
creates complexity with the deallocation. Specifically referring to the third
case for your example, delete [] p3 fails to deallocate the memory allocated.
You must loop delete []. Yet another reason to prefer STL vector for your
dynamic array needs.

Goran

unread,
Mar 29, 2011, 1:27:52 PM3/29/11
to
On Mar 29, 1:07 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> int (*p1)[5] = (int (*)[5])new int*[5]; /*2d array*/
> int (*p2)[5] = (int (*)[5])new int[5]; /*1d array*/
> int (*p3)[5] = new int[5][5]; /*2d array*/
> delete[] p1;
> delete[] p2;
> delete[] p3;
>
> What is the difference with the above deletes?

As far as I am concerned, difference is: first two are UB (platform-
specific at best), because of wrong casts in corresponding "new",
whereas the third one is correct.

> I don't know this term "array type erasure". What do you mean by that?

FAQ uses term "decay". I meant same thing (that was the term used to
explain the thing to me).

Goran.

Paul

unread,
Mar 29, 2011, 6:32:05 PM3/29/11
to

"Goran" <goran...@gmail.com> wrote in message
news:bed4b5d7-1577-4a11...@k9g2000yqi.googlegroups.com...

>On Mar 29, 1:07 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
>> int (*p1)[5] = (int (*)[5])new int*[5]; /*2d array*/
>> int (*p2)[5] = (int (*)[5])new int[5]; /*1d array*/
>> int (*p3)[5] = new int[5][5]; /*2d array*/
>> delete[] p1;
>> delete[] p2;
>> delete[] p3;
>>
>> What is the difference with the above deletes?
>
>As far as I am concerned, difference is: first two are UB (platform-
>specific at best), because of wrong casts in corresponding "new",
>whereas the third one is correct.

Why are they UB? After having a read through the rellevant pages of the
standard I don't think that it is UB. The standard specifically states that
the pointer returned from new must be castable.
Consider this more complex example:


class Base{
public:
Base() {std::cout<<"Constructing base\n";}

virtual ~Base(){std::cout<<"Destructing base\n";}
};

class Derived: public Base{
public:
Derived() {std::cout<<"Constructing derived\n";}
~Derived(){std::cout<<"Destructing derived\n";}
};

int main() {
Base (*p2)[3] = (Base (*)[3])new Derived[2][3];
delete[] p2;
}

The cast is required , otherwise you'd need to loop through the array
columns for allocation and deallocation..
I could cast it back prior to deletion with:
delete[] (Derived (*)[3])p2;

But this is unneccessary because Base type is an acceptable pointer type.
The type is only neccessay for the correct destruction of objects. For
example:
Base *p2 = new Derived[3];
delete[] p2;

is identical to
Base (*p2)[3] = (Base (*)[3])new Derived[3];
deletep[] p2;

The type that is relevant here is that it is Base or Derived, the number of
elements destructed is decided by the C runtime. As long as the dereferenced
pointer passed to delete has the same value as the pointer returned by new
all is ok, because it is converted to void* anyway. The C runtime decides
whether it deletes 3 objects or 1 , not the type system.
If int[3] and int* both point to the same address, then converted to void*
they are identical.
The C++ type system is only interested in if its an array of int-typ,
Derived-type , or Base-type, It not up to the type system to deicde how many
destructors to call.

It would be UB if you converted the pointer to a different type altogether
for example:
double* p = (double*)new int[6];
delete[] p;
This would be UB , because you are converting to a new type of array..

>
>> I don't know this term "array type erasure". What do you mean by that?
>
>FAQ uses term "decay". I meant same thing (that was the term used to
>explain the thing to me).

Ok I see you are talking about implicit pointer conversion.

HTH
Paul.

Kai-Uwe Bux

unread,
Mar 29, 2011, 7:53:04 PM3/29/11
to
Paul wrote:

>
> "Goran" <goran...@gmail.com> wrote in message
> news:bed4b5d7-1577-4a11...@k9g2000yqi.googlegroups.com...
>>On Mar 29, 1:07 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
>>> int (*p1)[5] = (int (*)[5])new int*[5]; /*2d array*/
>>> int (*p2)[5] = (int (*)[5])new int[5]; /*1d array*/
>>> int (*p3)[5] = new int[5][5]; /*2d array*/
>>> delete[] p1;
>>> delete[] p2;
>>> delete[] p3;
>>>
>>> What is the difference with the above deletes?
>>
>>As far as I am concerned, difference is: first two are UB (platform-
>>specific at best), because of wrong casts in corresponding "new",
>>whereas the third one is correct.
>
> Why are they UB? After having a read through the rellevant pages of the
> standard I don't think that it is UB.

We shall see.

> The standard specifically states that the pointer returned from new must
> be castable.

Correct: [5.2.10/7] states:

A pointer to an object can be explicitly converted to a pointer to an
object of different type.65) Except that converting an rvalue of type
"pointer to T1" to the type "pointer to T2" (where T1 and T2 are object
types and where the alignment requirements of T2 are no stricter than
those of T1) and back to its original type yields the original pointer
value, the result of such a pointer conversion is unspecified.

That implies that after casting, you have an unspecified result. The only
thing you can do with it, is casting back, and even that presupposes
compatible alignment requirement.

In particular, passing the unspecified value obtained by casting to delete
or delete [] is undefined behavior.


> Consider this more complex example:
> class Base{
> public:
> Base() {std::cout<<"Constructing base\n";}
> virtual ~Base(){std::cout<<"Destructing base\n";}
> };
>
> class Derived: public Base{
> public:
> Derived() {std::cout<<"Constructing derived\n";}
> ~Derived(){std::cout<<"Destructing derived\n";}
> };
>
> int main() {
> Base (*p2)[3] = (Base (*)[3])new Derived[2][3];
> delete[] p2;
> }
>
> The cast is required , otherwise you'd need to loop through the array
> columns for allocation and deallocation..
> I could cast it back prior to deletion with:
> delete[] (Derived (*)[3])p2;
>
> But this is unneccessary because Base type is an acceptable pointer type.

What do you mean by "acceptable"?

Also, the value of the variable p2 is _unspecified_ as it is obtained
through casting.

> The type is only neccessay for the correct destruction of objects. For
> example:
> Base *p2 = new Derived[3];
> delete[] p2;
>
> is identical to
> Base (*p2)[3] = (Base (*)[3])new Derived[3];
> deletep[] p2;
>
> The type that is relevant here is that it is Base or Derived, the number
> of elements destructed is decided by the C runtime. As long as the
> dereferenced pointer passed to delete has the same value as the pointer
> returned by new all is ok, because it is converted to void* anyway. The C
> runtime decides whether it deletes 3 objects or 1 , not the type system.

Sameness of value is not guaranteed by the standard (pretending we know what
it means). Consider:

int main () {
Derived (*p1) [3] = new Derived [2][3];
Base (*p2) [3] = (Base (*)[3]) p1;
assert( p1 == p2 );
}

This does not even compile as p1 and p2 are of different type.

> If int[3] and int* both point to the same address, then converted to void*
> they are identical.

So this is what we mean by "sameness of values". Ok, let's consider

int main () {
Derived (*p1) [3] = new Derived [2][3];
Base (*p2) [3] = (Base (*)[3]) p1;
assert( (void*)p1 == (void*)p2 );
}

Now, the code compiles. However, contrary to expectations, the assert is
allowed to _fail_ because the value of p2 is unspecified. In fact, using the
unspecified value as an argument for a cast is UB. So, we could do:

int main () {
Derived (*p1) [3] = new Derived [2][3];
Base (*p2) [3] = (Base (*)[3]) p1;
assert( p2 == (Base (*) [3]) p1 );
}

This looks as though it could not fail. However, the two sides of the == are
both unspecified values. It is neither clear that they are equal nor that
comparing them does not result in a core dump.

If you see more guarantees in the standard that would render any of the
above defined behavior, please cite them.

[...]


Best,

Kai-Uwe Bux

Paul

unread,
Mar 29, 2011, 10:55:53 PM3/29/11
to

"Kai-Uwe Bux" <jkher...@gmx.net> wrote in message
news:imtrd3$kq9$1...@hoshi.visyn.net...
But I didn't cast to a different object type, I casted to an array of
objects of the same type.
That quote is talking about converting between objects of a different types.


> In particular, passing the unspecified value obtained by casting to delete
> or delete [] is undefined behavior.

What is unspecified , the cast does not make the pointer *unspecified*


>
>
>> Consider this more complex example:
>> class Base{
>> public:
>> Base() {std::cout<<"Constructing base\n";}
>> virtual ~Base(){std::cout<<"Destructing base\n";}
>> };
>>
>> class Derived: public Base{
>> public:
>> Derived() {std::cout<<"Constructing derived\n";}
>> ~Derived(){std::cout<<"Destructing derived\n";}
>> };
>>
>> int main() {
>> Base (*p2)[3] = (Base (*)[3])new Derived[2][3];
>> delete[] p2;
>> }
>>
>> The cast is required , otherwise you'd need to loop through the array
>> columns for allocation and deallocation..
>> I could cast it back prior to deletion with:
>> delete[] (Derived (*)[3])p2;
>>
>> But this is unneccessary because Base type is an acceptable pointer type.
>
> What do you mean by "acceptable"?

Acceptable pointer type, that is a base(with virtual destructor) or derived
class. There are probably many other acceptable pointer conversions which
are Implementation specific e.g: short to int where they are both the same
size.


>
> Also, the value of the variable p2 is _unspecified_ as it is obtained
> through casting.

Casting doesn't make it *unspecified*.

>
>> The type is only neccessay for the correct destruction of objects. For
>> example:
>> Base *p2 = new Derived[3];
>> delete[] p2;
>>
>> is identical to
>> Base (*p2)[3] = (Base (*)[3])new Derived[3];
>> deletep[] p2;
>>
>> The type that is relevant here is that it is Base or Derived, the number
>> of elements destructed is decided by the C runtime. As long as the
>> dereferenced pointer passed to delete has the same value as the pointer
>> returned by new all is ok, because it is converted to void* anyway. The C
>> runtime decides whether it deletes 3 objects or 1 , not the type system.
>
> Sameness of value is not guaranteed by the standard (pretending we know
> what
> it means). Consider:
>
> int main () {
> Derived (*p1) [3] = new Derived [2][3];
> Base (*p2) [3] = (Base (*)[3]) p1;
> assert( p1 == p2 );
> }
>
> This does not even compile as p1 and p2 are of different type.

That doesn't mean the values are not the same though does it.

>
>> If int[3] and int* both point to the same address, then converted to
>> void*
>> they are identical.
>
> So this is what we mean by "sameness of values". Ok, let's consider
>
> int main () {
> Derived (*p1) [3] = new Derived [2][3];
> Base (*p2) [3] = (Base (*)[3]) p1;
> assert( (void*)p1 == (void*)p2 );
> }
>
> Now, the code compiles. However, contrary to expectations, the assert is
> allowed to _fail_ because the value of p2 is unspecified. In fact, using
> the
> unspecified value as an argument for a cast is UB. So, we could do:

I don't know what your problem is with understand the meaning of two of the
same values.
its simple:
float f = 65;
int x = 65;
long l = 65;

same values.


>
> int main () {
> Derived (*p1) [3] = new Derived [2][3];
> Base (*p2) [3] = (Base (*)[3]) p1;
> assert( p2 == (Base (*) [3]) p1 );
> }
>
> This looks as though it could not fail. However, the two sides of the ==
> are
> both unspecified values. It is neither clear that they are equal nor that
> comparing them does not result in a core dump.

I don't have a clue what you are talking about, what is an unspecified
value? What fails?

A pointers' value is the address it points to , if two pointers point to the
same address they have they same value, simple as that.

>
> If you see more guarantees in the standard that would render any of the
> above defined behavior, please cite them.
>

What guarantees you talknig about here?

Goran

unread,
Mar 30, 2011, 3:12:23 AM3/30/11
to
On Mar 30, 12:32 am, "Paul" <pchris...@yahoo.co.uk> wrote:
> "Goran" <goran.pu...@gmail.com> wrote in message

>
> news:bed4b5d7-1577-4a11...@k9g2000yqi.googlegroups.com...
>
> >On Mar 29, 1:07 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> >> int (*p1)[5] = (int (*)[5])new int*[5]; /*2d array*/
> >> int (*p2)[5] = (int (*)[5])new int[5]; /*1d array*/
> >> int (*p3)[5] = new int[5][5]; /*2d array*/
> >> delete[] p1;
> >> delete[] p2;
> >> delete[] p3;
>
> >> What is the difference with the above deletes?
>
> >As far as I am concerned, difference is: first two are UB (platform-
> >specific at best), because of wrong casts in corresponding "new",
> >whereas the third one is correct.
>
> Why are they UB? After having a read through the rellevant pages of the
> standard I don't think that it is UB. The standard specifically states that
> the pointer returned from new must be castable.

Return type of "new int(*)[5]" is int**. You cast that into int(*)[5],
using C cast. That, as far as I can see, ends up in same effect as
reinterpret_cast, and reinterpret_cast is UB (or platform specific at
best).

> Consider this more complex example:
> class Base{
> public:
>  Base() {std::cout<<"Constructing base\n";}
>  virtual ~Base(){std::cout<<"Destructing base\n";}
>
> };
>
> class Derived: public Base{
>  public:
>  Derived() {std::cout<<"Constructing derived\n";}
>  ~Derived(){std::cout<<"Destructing derived\n";}
>
> };
>
> int main() {
>  Base (*p2)[3] = (Base (*)[3])new Derived[2][3];
>  delete[] p2;
>
> }
>
> The cast is required ,  otherwise you'd need to loop through the array
> columns for allocation and deallocation..

First, the cast is not required, because

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

works just as well.

Second, the problem with your exact example is that in practice just
does not work. And I mean, at all!

Try this:

class Base{
public:
Base() : i(0) {}
int i;
};

class Derived: public Base{
public:

Derived() : j(1) {}
int j;
};

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

const Base& b = p2[0][1];
assert(0 == b.i); // Fires on common implementations
assert(1 == b.i); // Does not fire on common implementations. Eh!?

Of course, problem is that pointer returned by "new Derived[2][3]" and
"Base (*)[3]" have unrelated types, and my code snippet shows why that
is required.

Goran.

> >FAQ uses term "decay". I meant same thing (that was the term used to
> >explain the thing to me).
>
> Ok I see you are talking about implicit pointer conversion.

Nice try ;-);

Goran.

Kai-Uwe Bux

unread,
Mar 30, 2011, 3:52:33 AM3/30/11
to
Paul wrote:

[...]

Ok, so you are saying that the C-style cast you are using is _not_ governed
by clause [5.2.10/7]. Please specify which clause of the standard you are
relying on in determining the behavior of the cast expression.


Best,

Kai-Uwe Bux

cg_chas

unread,
Mar 30, 2011, 4:30:00 AM3/30/11
to

But you did cast to a different type in both of the above cases that you casted:

1) from int** to int(*)[5]
2) from int* to int(*)[5]

or in language that even you should understand since it appears that you are
confused by the Standard's use of what pointer to and object of different type
means:

1) from "pointer to int pointer" to "pointer to array of int"
2) from "pointer to int" to "pointer to array of int"

Once again, this takes us back to all of the previous message threads that you
have started which demonstrate some form of your confusion with the fact that a
pointer to int and pointer to array of int are not the same thing.

Now whether or not there are stricter alignment requirements for T2 than T1 is
another story. I do not think there is under Windows for the above types, but
the idea is that UB is potentially there where C++ is concerned. Something that
could easily be remedied by not casting the return in the first place.

Kai-Uwe Bux

unread,
Mar 30, 2011, 4:33:27 AM3/30/11
to
Here is a data point:

#include <iostream>

class BaseA{
public:
int k;
BaseA() {std::cout<<"Constructing base a\n";}
virtual ~BaseA(){std::cout<<"Destructing base a\n";}
};

class BaseB {
public:
int i;
BaseB() {std::cout<<"Constructing base b\n";}
virtual ~BaseB(){std::cout<<"Destructing base b\n";}
};

class Derived: public BaseA, BaseB {
public:
int j;


Derived() {std::cout<<"Constructing derived\n";}
~Derived(){std::cout<<"Destructing derived\n";}
};

int main() {


Derived (*p1) [3] = new Derived [2][3];

BaseB (*p2)[3] = (BaseB (*)[3])p1;
delete [] p2;
}

This program segfaults on my machine.

I think, it is allowed to do so.


Best,

Kai-Uwe Bux

Paul

unread,
Mar 30, 2011, 6:36:28 AM3/30/11
to

>"Goran" <goran...@gmail.com> wrote in message
>news:270b8feb-2801-4a15-a7a9->05f4f5...@p13g2000yqh.googlegroups.com...

>On Mar 30, 12:32 am, "Paul" <pchris...@yahoo.co.uk> wrote:
>> "Goran" <goran.pu...@gmail.com> wrote in message
>>
>> news:bed4b5d7-1577-4a11...@k9g2000yqi.googlegroups.com...
>>
>> >On Mar 29, 1:07 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
>> >> int (*p1)[5] = (int (*)[5])new int*[5]; /*2d array*/
>> >> int (*p2)[5] = (int (*)[5])new int[5]; /*1d array*/
>> >> int (*p3)[5] = new int[5][5]; /*2d array*/
>> >> delete[] p1;
>> >> delete[] p2;
>> >> delete[] p3;
>>
>> >> What is the difference with the above deletes?
>>
>> >specific at best), because of wrong casts in corresponding "new",
>> >whereas the third one is correct.
>>
>> Why are they UB? After having a read through the rellevant pages of the
>> standard I don't think that it is UB. The standard specifically states
>> that
>> the pointer returned from new must be castable.
>
>Return type of "new int(*)[5]" is int**. You cast that into int(*)[5],
>using C cast. That, as far as I can see, ends up in same effect as
>reinterpret_cast, and reinterpret_cast is UB (or platform specific at
>best).

So, as far as you can see, any use of a c-style cast will immediately cause
UB?

<snip>


>Of course, problem is that pointer returned by "new Derived[2][3]" and
>"Base (*)[3]" have unrelated types, and my code snippet shows why that
>is required.

Your code shows me nothing except that you are a noob who uses assert, If
you want to expalin something to me in code please don't use noob statements
like assert.

> >FAQ uses term "decay". I meant same thing (that was the term used to
> >explain the thing to me).
>
> Ok I see you are talking about implicit pointer conversion.

Nice try ;-);

What does this mean? What am I trying to do in your mind?

Sorry for snipping etc but dont have time to manually indent all that crap.

Paul

unread,
Mar 30, 2011, 6:39:30 AM3/30/11
to

"Kai-Uwe Bux" <jkher...@gmx.net> wrote in message
news:imupsn$tos$1...@hoshi.visyn.net...
I will need to look at this later when I have more time. As this is a
different inheritance pattern maybe there are some isssues

Paul

unread,
Mar 30, 2011, 6:44:46 AM3/30/11
to

"Kai-Uwe Bux" <jkher...@gmx.net> wrote in message
news:imung5$t2f$1...@hoshi.visyn.net...
I was saying the cast wasn't an issue with me, I don't see things in such a
way that every cast produces UB.
A cast from int* to int*[] doesn't seem like a major conversion of any
major concern to me.

Goran

unread,
Mar 30, 2011, 8:26:17 AM3/30/11
to
On Mar 30, 12:36 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> >"Goran" <goran.pu...@gmail.com> wrote in message
> >news:270b8feb-2801-4a15-a7a9->05f4f5ab8__BEGIN_MASK_n#9g02mG7!__...__END_MASK_i?a63jfAD$z...@p13g2000yqh.googlegroups.com...

> >On Mar 30, 12:32 am, "Paul" <pchris...@yahoo.co.uk> wrote:
> >> "Goran" <goran.pu...@gmail.com> wrote in message
>
> >>news:bed4b5d7-1577-4a11...@k9g2000yqi.googlegroups.com...
>
> >> >On Mar 29, 1:07 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> >> >> int (*p1)[5] = (int (*)[5])new int*[5]; /*2d array*/
> >> >> int (*p2)[5] = (int (*)[5])new int[5]; /*1d array*/
> >> >> int (*p3)[5] = new int[5][5]; /*2d array*/
> >> >> delete[] p1;
> >> >> delete[] p2;
> >> >> delete[] p3;
>
> >> >> What is the difference with the above deletes?
>
> >> >specific at best), because of wrong casts in corresponding "new",
> >> >whereas the third one is correct.
>
> >> Why are they UB? After having a read through the rellevant pages of the
> >> standard I don't think that it is UB. The standard specifically states
> >> that
> >> the pointer returned from new must be castable.
>
> >Return type of "new int(*)[5]" is int**. You cast that into int(*)[5],
> >using C cast. That, as far as I can see, ends up in same effect as
> >reinterpret_cast, and reinterpret_cast is UB (or platform specific at
> >best).
>
> So, as far as you can see, any use of a c-style cast will immediately cause
> UB?

Not will. Could. Your cast up there __will__, however (and a very
simple example has shown that).

> >Of course, problem is that pointer returned by "new Derived[2][3]" and
> >"Base (*)[3]" have unrelated types, and my code snippet shows why that
> >is required.
>
> Your code shows me nothing except that you are a noob who uses assert, If
> you want to expalin something to me in code please don't use noob statements
> like assert.

First, assert is not a statement, it's a function. Second, it's use is
incidental to the problem. Noob or not, assert shows that your cast
does not work.

In slightly more detail: in common implementations, object's memory
layout is such that your cast, on your example, fails horribly. Line

const Base& b = p2[0][1];

does not produce a reference to b (and it should). It does not do it,
because the cast on the line where new is called is __wrong__.

In even more detail: what new allocated (on common implementations) is
6 consecutive instances of Derived. So let's presume a 32-bit platform
and a common implementation. New gives (memory layout):

32 bits: Base.i
32 bits: Derived.j
32 bits: Base.i
32 bits: Derived.j
... 6 of those in total

You tried to cast that to (memory layout on common implementations):

32 bits: Base.i
32 bits: Base.i
... 6 of those in total

Your cast causes "b" to "reference" Derived.j, which makes no sense
whatsoever. "assert" was only there to show you this. I hoped not so
many words were needed, but alas...

Goran.

Paul

unread,
Mar 30, 2011, 8:41:13 AM3/30/11
to

"Goran" <goran...@gmail.com> wrote in message
news:94faa1e8-754e-4144...@a26g2000vbo.googlegroups.com...

------------------------------------------

Who the hell do you think you are ?
You cant even communicate properly I cant be arsed with arseholes who cant
communicate properly.
Im not gonna bother indenting and making an effort for someone who obviously
thinks he is abov eme.

I told you your example showed me nothing except that you are some noob who
uses *STATEMENTS* like assert

Goran

unread,
Mar 30, 2011, 9:28:11 AM3/30/11
to
On Mar 30, 2:41 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> I told you your example showed me nothing except that you are some noob who
> uses *STATEMENTS* like assert

I was mistaken, I apologize. assert is not a function, it's rather a
macro.

It's not a statement though. Please refer to section 6 of the current
language standard for more detail on what a statement is.

Goran.

Paul

unread,
Mar 30, 2011, 10:00:33 AM3/30/11
to

"Goran" <goran...@gmail.com> wrote in message
news:536c0fc1-460b-4804...@k30g2000yqb.googlegroups.com...


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

I dont care what its called in the standards I called it a statement and you
knew what i meant.
What I dont understand is what exactly your argument is, you fail to
communicate properly.
You said something was UB but no expalanation, just because it appeared to
be UB to you.
Now you are blabbing on about some assert thing. WHat exactly has all this
got to do with delete[] ?

Paul

unread,
Mar 30, 2011, 10:38:31 AM3/30/11
to

"Kai-Uwe Bux" <jkher...@gmx.net> wrote in message
news:imupsn$tos$1...@hoshi.visyn.net...
Ok I had a quick look at this.
This works perfectly ok on my machine. So are you are saying is that its UB
to cast a pointer to Derived into a pointer to BaseB?
Or are you saying that its only UB to cast a pointer of Derived (*)[size] to
BaseB (*)[size], but its ok to cast a Derived* to a baseB*?
As far as I was aware is perfectly ok to downcast to a Base class. As long
as the Base class has a virtual destructor the object destruction will
destruct the whole Dervied object.

Goran

unread,
Mar 30, 2011, 10:47:30 AM3/30/11
to
On Mar 30, 4:00 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> What I dont understand is what exactly your argument is, you fail to
> communicate properly.
> You said something was UB but no expalanation, just because it appeared to
> be UB to you.
> Now you are blabbing on about some assert thing. WHat exactly has all this
> got to do with delete[] ?

Your cast is on the new side invokes UB. By consequence, your examples
are buggy, and so is your call to operator[].

You do not seem to accept that cast invokes UB, so I made you a piece
of code that shows why your cast is, and should be, UB.

For that piece of code, I used assert to ascertain what should be true
(that "0" equals "b.i"). If you compile this snippet without NDEBUG,
"assert(0 == b.i)" should not fire, because, clearly, Base() sets i to
0. And yet, this assert does fire (on common implementations). Why?
Because your cast invoked UB. Consequently, everything else is wrong,
including delete[] you're trying to pull off.

Goran.

Leigh Johnston

unread,
Mar 30, 2011, 11:14:00 AM3/30/11
to
On 30/03/2011 15:38, Paul wrote:
> As far as I was aware is perfectly ok to downcast to a Base class. As
> long as the Base class has a virtual destructor the object destruction
> will destruct the whole Dervied object.

Casting from derived to base is called "upcasting" not "downcasting".

/Leigh

Paul

unread,
Mar 30, 2011, 1:06:28 PM3/30/11
to

"Leigh Johnston" <le...@i42.co.uk> wrote in message
news:dqydndSmfoUl1Q7Q...@giganews.com...
Thats a rather back to front way of looking at it. Casting to a subobject is
casting up?

Paul

unread,
Mar 30, 2011, 1:14:07 PM3/30/11
to

"Goran" <goran...@gmail.com> wrote in message
news:1d20e918-d384-43db...@v8g2000yqb.googlegroups.com...

On Mar 30, 4:00 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> What I dont understand is what exactly your argument is, you fail to
> communicate properly.
> You said something was UB but no expalanation, just because it appeared to
> be UB to you.
> Now you are blabbing on about some assert thing. WHat exactly has all this
> got to do with delete[] ?

Your cast is on the new side invokes UB. By consequence, your examples
are buggy, and so is your call to operator[].

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Why?
Please explain why it is UB?

Any time we cast in C++ we produce UB?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

You do not seem to accept that cast invokes UB, so I made you a piece
of code that shows why your cast is, and should be, UB.

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Your code doesn't prove the cast is UB. I would accept it if it is UB but as
far as I can see all the standard says is that new must return a castable
pointer, this implies that its allowed to be casted.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

For that piece of code, I used assert to ascertain what should be true
(that "0" equals "b.i"). If you compile this snippet without NDEBUG,
"assert(0 == b.i)" should not fire, because, clearly, Base() sets i to
0. And yet, this assert does fire (on common implementations). Why?
Because your cast invoked UB.

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Eh? Because you code asserts something to be not equal you assert this to
mean the cast produces UB? How do you come to that conclusion?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Leigh Johnston

unread,
Mar 30, 2011, 1:15:21 PM3/30/11
to

Think about how you draw a family tree: ancestors toward the top;
descendants toward the bottom (the tree is upside down).

Anyway it doesn't matter how it *seems* to you; what is important is to
be technically accurate and to use correct terminology: casting from
derived to base is called "upcasting"; casting from base to derived is
called "downcasting".

/Leigh

Paul

unread,
Mar 30, 2011, 1:22:51 PM3/30/11
to

"Leigh Johnston" <le...@i42.co.uk> wrote in message
news:sNOdnZtNWPu3-A7Q...@giganews.com...

> On 30/03/2011 18:06, Paul wrote:
>>
>> "Leigh Johnston" <le...@i42.co.uk> wrote in message
>> news:dqydndSmfoUl1Q7Q...@giganews.com...
>>> On 30/03/2011 15:38, Paul wrote:
>>>> As far as I was aware is perfectly ok to downcast to a Base class. As
>>>> long as the Base class has a virtual destructor the object destruction
>>>> will destruct the whole Dervied object.
>>>
>>> Casting from derived to base is called "upcasting" not "downcasting".
>>>
>> Thats a rather back to front way of looking at it. Casting to a
>> subobject is casting up?
>
> Think about how you draw a family tree: ancestors toward the top;
> descendants toward the bottom (the tree is upside down).

A family tree is exact opposite of a class inheritance, a parent object is
the most derived object.
In a family tree the children are most derived.

>
> Anyway it doesn't matter how it *seems* to you; what is important is to be
> technically accurate and to use correct terminology: casting from derived
> to base is called "upcasting"; casting from base to derived is called
> "downcasting".
>

Yes says the proven idiot who thinks p doesn't point to an array with:
int* p = new int[5]

Goran

unread,
Mar 30, 2011, 1:33:56 PM3/30/11
to
On Mar 30, 7:14 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> "Goran" <goran.pu...@gmail.com> wrote in message

>
> news:1d20e918-d384-43db...@v8g2000yqb.googlegroups.com...
> On Mar 30, 4:00 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
>
> > What I dont understand is what exactly your argument is, you fail to
> > communicate properly.
> > You said something was UB but no expalanation, just because it appeared to
> > be UB to you.
> > Now you are blabbing on about some assert thing. WHat exactly has all this
> > got to do with delete[] ?
>
> Your cast is on the new side invokes UB. By consequence, your examples
> are buggy, and so is your call to operator[].
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> Why?
> Please explain why it is UB?

Because you are casting from a pointer of one type to a pointer of an
unrelated type (and that's what the compiler told you, too, when you
tried without a cast, now did it?)

> You do not seem to accept that cast invokes UB, so I made you a piece
> of code that shows why your cast is, and should be, UB.
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> Your code doesn't prove the cast is UB.

It does. See below.

> For that piece of code, I used assert to ascertain what should be true
> (that "0" equals "b.i"). If you compile this snippet without NDEBUG,
> "assert(0 == b.i)" should not fire, because, clearly, Base() sets i to
> 0. And yet, this assert does fire (on common implementations). Why?
> Because your cast invoked UB.
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> Eh? Because you code asserts something to be not equal you assert this to
> mean the cast produces UB? How do you come to that conclusion?
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

That something is b.i, which is initialized to 0 and never changed.
Yet, assert does fire.

My claim is that it fires because cast was UB, and, on common
implementations, result is that code sees that b.i equals one, not
zero.

My claim is that implementation is correct in everything it has done,
that code is correct in every detail, except for the UB cast. If cast
wasn't UB, assert(0 == b.i) would not fire. Since it does, it's
because cast is UB.

Goran.

Leigh Johnston

unread,
Mar 30, 2011, 1:38:54 PM3/30/11
to
On 30/03/2011 18:22, Paul wrote:
>
> "Leigh Johnston" <le...@i42.co.uk> wrote in message
> news:sNOdnZtNWPu3-A7Q...@giganews.com...
>> On 30/03/2011 18:06, Paul wrote:
>>>
>>> "Leigh Johnston" <le...@i42.co.uk> wrote in message
>>> news:dqydndSmfoUl1Q7Q...@giganews.com...
>>>> On 30/03/2011 15:38, Paul wrote:
>>>>> As far as I was aware is perfectly ok to downcast to a Base class. As
>>>>> long as the Base class has a virtual destructor the object destruction
>>>>> will destruct the whole Dervied object.
>>>>
>>>> Casting from derived to base is called "upcasting" not "downcasting".
>>>>
>>> Thats a rather back to front way of looking at it. Casting to a
>>> subobject is casting up?
>>
>> Think about how you draw a family tree: ancestors toward the top;
>> descendants toward the bottom (the tree is upside down).
>
> A family tree is exact opposite of a class inheritance, a parent object
> is the most derived object.
> In a family tree the children are most derived.

A family tree was an example of a tree which you typically draw upside
down (the root is at the top); an inheritance hierarchy is typically
viewed as a tree where the base classes are at the root of the tree and
similar to a family tree the root is at the top hence the term "upcast".

>
>>
>> Anyway it doesn't matter how it *seems* to you; what is important is
>> to be technically accurate and to use correct terminology: casting
>> from derived to base is called "upcasting"; casting from base to
>> derived is called "downcasting".
>>
> Yes says the proven idiot who thinks p doesn't point to an array with:
> int* p = new int[5]

p is not a pointer to an array; p is a pointer to an int.

You are the one who continually provides evidence to everyone reading
your posts as to who the idiot actually is; you certainly have yet to
provide any evidence or proof that those who continually correct you are
idiots although giving a troll such as yourself any time probably *is*
idiotic.

If you are not a troll and you actually believe the bullshit you post
then your cause is a hopeless one.

/Leigh

Kai-Uwe Bux

unread,
Mar 30, 2011, 1:44:07 PM3/30/11
to
Paul wrote:

Not _every_ cast. Just the one in your code :-)

> A cast from int* to int*[] doesn't seem like a major conversion of any
> major concern to me.

It is a conversion not governed by anything else than [5.2.10/7]. And the
governing clause [5.2.10/7] specifies that the result of the cast is
unspecified. Using those unspecified values farther down the road in any way
not listed in [5.2.10/7] is undefined behavior as per:

1.3.12 undefined behavior
behavior, such as might arise upon use of an erroneous program construct
or erroneous data, for which this International Standard imposes no
requirements. Undefined behavior may also be expected when this
International Standard omits the description of any explicit definition of
behavior.


Best,

Kai-Uwe Bux

Kai-Uwe Bux

unread,
Mar 30, 2011, 2:02:57 PM3/30/11
to
Paul wrote:

I don't say that.

> Or are you saying that its only UB to cast a pointer of Derived (*)[size]
> to BaseB (*)[size], but its ok to cast a Derived* to a baseB*?

I don't even say that. What I say is that casting the pointer p1 (of type
Derived(*)[3]) to the type (BaseB(*)[3]) results in an unspecified value of
p2. What is UB is calling delete[] on the unspecified value p2.

> As far as I was aware is perfectly ok to downcast to a Base class. As long
> as the Base class has a virtual destructor the object destruction will
> destruct the whole Dervied object.

True. If we had

Derived* p1 = new Derived;
BaseB* p2 = (BaseB*)p1;
delete p2;

everything would be perfectly fine. Note, however, that the case is
_entirely_ different, starting with the C-style cast (BaseB*)p1 being a
static_cast<> as opposed to the reinterpret_cast<> from the previous
snippet. Now, the (redundant) cast is governed by [5.2.9/2]. The delete
expression is governed by [5.3.5/3].

Note, however, that this snippet has UB:

Derived* p1 = new Derived [3];
BaseB* p2 = (BaseB*)p1; // fine so far, but p2[1] would be UB
delete [] p2; // UB as per [5.3.5/3]

This involves the distinction of dynamic and static types: p2 has dynamic
type Derived* and static type BaseB*.


Best,

Kai-Uwe Bux

Paul

unread,
Mar 30, 2011, 3:18:19 PM3/30/11
to

"Kai-Uwe Bux" <jkher...@gmx.net> wrote in message
news:imvq59$89a$1...@hoshi.visyn.net...
Oh right so its a case of any time I do a cast its UB because you say so.
Like I bother what people like you think if thats the case.

Paul

unread,
Mar 30, 2011, 3:21:55 PM3/30/11
to

"Kai-Uwe Bux" <jkher...@gmx.net> wrote in message
news:imvr8j$8n6$1...@hoshi.visyn.net...
I thought you might actually have a valid point, but now its quite clear
your just another idiot who has no other objective than to prove anything I
say is wrong.
I don't really care what people like you think tbh 99% of the time you don't
have a clue what you're talking about.

Paul

unread,
Mar 30, 2011, 3:24:14 PM3/30/11
to

"Goran" <goran...@gmail.com> wrote in message
news:c7844c1b-31da-46c7...@27g2000yqv.googlegroups.com...

On Mar 30, 7:14 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> "Goran" <goran.pu...@gmail.com> wrote in message
>
> news:1d20e918-d384-43db...@v8g2000yqb.googlegroups.com...
> On Mar 30, 4:00 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
>
> > What I dont understand is what exactly your argument is, you fail to
> > communicate properly.
> > You said something was UB but no expalanation, just because it appeared
> > to
> > be UB to you.
> > Now you are blabbing on about some assert thing. WHat exactly has all
> > this
> > got to do with delete[] ?
>
> Your cast is on the new side invokes UB. By consequence, your examples
> are buggy, and so is your call to operator[].
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> Why?
> Please explain why it is UB?

Because you are casting from a pointer of one type to a pointer of an
unrelated type (and that's what the compiler told you, too, when you
tried without a cast, now did it?)

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

No my code compiles fine, The types are not unrelated they are both int
types.
I can cast from int[] to int* implicitly because its a realated type.

cg_chas

unread,
Mar 30, 2011, 3:47:38 PM3/30/11
to

UB doesn't mean that something will or will not work.
It means that the Standard simply does not guarantee the behaviour.

>>>So are you are saying is that its
>>> UB to cast a pointer to Derived into a pointer to BaseB?
>>
>> I don't say that.
>>
>>> Or are you saying that its only UB to cast a pointer of Derived (*)[size]
>>> to BaseB (*)[size], but its ok to cast a Derived* to a baseB*?
>>
>> I don't even say that. What I say is that casting the pointer p1 (of type
>> Derived(*)[3]) to the type (BaseB(*)[3]) results in an unspecified value
>> of
>> p2. What is UB is calling delete[] on the unspecified value p2.
>>
>I thought you might actually have a valid point, but now its quite clear
>your just another idiot who has no other objective than to prove anything I
>say is wrong.

Everybody that disagrees with Paul is an idiot, espectially when they use logic
or proper citation of the Standard to prove him wrong.

cg_chas

unread,
Mar 30, 2011, 4:04:57 PM3/30/11
to
On Wed, 30 Mar 2011 18:22:51 +0100, "Paul" <pchr...@yahoo.co.uk> wrote:

>
>"Leigh Johnston" <le...@i42.co.uk> wrote in message
>news:sNOdnZtNWPu3-A7Q...@giganews.com...
>> On 30/03/2011 18:06, Paul wrote:
>>>
>>> "Leigh Johnston" <le...@i42.co.uk> wrote in message
>>> news:dqydndSmfoUl1Q7Q...@giganews.com...
>>>> On 30/03/2011 15:38, Paul wrote:
>>>>> As far as I was aware is perfectly ok to downcast to a Base class. As
>>>>> long as the Base class has a virtual destructor the object destruction
>>>>> will destruct the whole Dervied object.
>>>>
>>>> Casting from derived to base is called "upcasting" not "downcasting".
>>>>
>>> Thats a rather back to front way of looking at it. Casting to a
>>> subobject is casting up?
>>
>> Think about how you draw a family tree: ancestors toward the top;
>> descendants toward the bottom (the tree is upside down).
>
>A family tree is exact opposite of a class inheritance, a parent object is
>the most derived object.
>In a family tree the children are most derived.

I am starting to think you are making shit up as you go along here. And when
you are called on your wrongness, you become pridefully defensive and argue the
most inane points instead of just acknowledging those who have helped you to be
correct.

TCPPPL 15.4 Class Hierarchies:
"Casting from base class to a derived class is often called a downcast because
of the convention of drawing inheritance trees growing from the root down.
Similarly, a cast from the derived class to the base is called an upcast."

Of course, you're entitled to your own language with its own vocabulary and its
own set of terms, but keep in mind that when you come to these forums, you are
going to be severely limited in such a way that you feel that everybody here is
trying to prove everything that you say is wrong.

>
>>
>> Anyway it doesn't matter how it *seems* to you; what is important is to be
>> technically accurate and to use correct terminology: casting from derived
>> to base is called "upcasting"; casting from base to derived is called
>> "downcasting".
>>
>Yes says the proven idiot who thinks p doesn't point to an array with:
>int* p = new int[5]

Ahh, I see, you're still confused. Well I am all too happy to help. That's
what we are here for :)

p is a pointer to the single int that was returned by new.
p is pointer of "int type", not "array of int type"
p only points to a single int

Anything else that you think p points to is meaningful only in your mind.

Consult ISO/IEC 14882 for further information and clarification if you are still
confused.

By the way, I proudly stand among those that you call idiots since this
distringuished group of idiots are all of those that have successfully used
simple logic and proper citation of The Standard to prove you wrong.

Joshua Maurice

unread,
Mar 30, 2011, 5:04:08 PM3/30/11
to
On Mar 30, 1:04 pm, cg_chas <cg_c...@hotmail.com> wrote:
> On Wed, 30 Mar 2011 18:22:51 +0100, "Paul" <pchris...@yahoo.co.uk> wrote:
>> [...]

> I am starting to think you are making shit up as you go along here.  

Welcome to the club. The rest of us realized this a month or two ago.
Just ignore the troll.

Paul

unread,
Mar 30, 2011, 7:42:11 PM3/30/11
to

"Leigh Johnston" <le...@i42.co.uk> wrote in message
news:JY-dnaCxyM0y9w7Q...@giganews.com...
No p points to the initial element *of an array*, by definiton it points to
an array.

>
> You are the one who continually provides evidence to everyone reading your
> posts as to who the idiot actually is; you certainly have yet to provide
> any evidence or proof that those who continually correct you are idiots
> although giving a troll such as yourself any time probably *is* idiotic.
>
> If you are not a troll and you actually believe the bullshit you post then
> your cause is a hopeless one.
>

Very good but it's obvious to anyone, with isn't an idiot, that you are an
idiot. As for the idiots who agree with you, I don't really care what they
think .
:-)

Leigh Johnston

unread,
Mar 30, 2011, 7:52:12 PM3/30/11
to
On 31/03/2011 00:42, Paul wrote:
[...]

>>>> Anyway it doesn't matter how it *seems* to you; what is important is
>>>> to be technically accurate and to use correct terminology: casting
>>>> from derived to base is called "upcasting"; casting from base to
>>>> derived is called "downcasting".
>>>>
>>> Yes says the proven idiot who thinks p doesn't point to an array with:
>>> int* p = new int[5]
>>
>> p is not a pointer to an array; p is a pointer to an int.
> No p points to the initial element *of an array*, by definiton it points
> to an array.

Whilst p does point to the initial element of an array that does not
mean that p is a pointer to an array; p is a pointer to an int.

[...]

/Leigh

Paul

unread,
Mar 30, 2011, 9:22:27 PM3/30/11
to

"Leigh Johnston" <le...@i42.co.uk> wrote in message
news:6ZqdnRJoifyzXw7Q...@giganews.com...
If p points to the intial element *OF AN ARRAY*, then by defintion it points
to an array.
Were you born stupid or did you grow into it?


Goran

unread,
Mar 31, 2011, 2:31:29 AM3/31/11
to
On Mar 30, 9:24 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> Because you are casting from a pointer of one type to a pointer of an
> unrelated type (and that's what the compiler told you, too, when you
> tried without a cast, now did it?)
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
>
> No my code compiles fine

Irrelevant. There's gigabytes of source that compile fine, but does
not work.

> , The types are not unrelated they are both int
> types.
> I can cast from int[] to int* implicitly because its a realated type.

You can, but that is irrelevant for what you're trying to do. Besides,
cast is already implicit, so why would you!?

The problem is elsewhere: when you do "new TYPE[size1][size2]", the
type of result is "TYPE**", and that is __unrelated__ to "TYPE (*)
[size2]". Ppeople already have quoted you relevant portions of the
standard, and I even went through the hassle of showing you, in great
detail, __why__ what you are trying to do can't work well. In the
process of doing so, I offered you, effectively, a __proof__ that your
cast is UB (this type of proof is commonly called "proof by
contradiction", and I can rephrase my proof more formally if you
wish).

You should take note of this, I believe: by your own words: "I can
cast from int[] to int* __implicitly__ (emphasis mine) because its a
realated type". However, no implementation allowed you to assign
result of new TYPE[size1][size2] to TYPE(*)[size2]. There is __no__
implicit conversion there (and with a good reason, too, see above). So
you resorted to a cast. An UB one.

Goran.

Goran

unread,
Mar 31, 2011, 2:44:57 AM3/31/11
to
On Mar 31, 3:22 am, "Paul" <pchris...@yahoo.co.uk> wrote:
> >>>> Yes says the proven idiot who thinks p doesn't point to an array with:
> >>>> int* p = new int[5]
>
> >>> p is not a pointer to an array; p is a pointer to an int.
> >> No p points to the initial element *of an array*, by definiton it points
> >> to an array.

I don't know what definition you are talking about, but either the
definition, or your interpretation thereof, is wrong.

Return type of expression "new TYPE[5]" is "TYPE*", not e.g. TYPE[5],
or, I dunno, TYPE(*)[5]. Array (as in TYPE[size]) is in no way
involved there. Arrays and pointers mix in some other contexts^^^.

It looks like the syntax (new TYPE[5]), that resembles an array
declaration, confuses you. You might want to think of it this way:

int* p = new int(1); // p is a pointer to int.
p = new int[2];
// p is __still__ a pointer to int
int i;
p = &i;
// p is __still__ a pointer to int
int a[3];
p = a; // ^^^ implicit array-to-pointer conversion
// p is __still__ a pointer to int

You seem to believe that there is something as pointer-to-array
conversion (or pointer-to-pointertoarray conversion). That belief is
wrong.

Goran.

Paul

unread,
Mar 31, 2011, 5:52:48 AM3/31/11
to

"Goran" <goran...@gmail.com> wrote in message
news:362fae78-1af4-4f00...@k22g2000yqh.googlegroups.com...

On Mar 31, 3:22 am, "Paul" <pchris...@yahoo.co.uk> wrote:
> >>>> Yes says the proven idiot who thinks p doesn't point to an array
> >>>> with:
> >>>> int* p = new int[5]
>
> >>> p is not a pointer to an array; p is a pointer to an int.
> >> No p points to the initial element *of an array*, by definiton it
> >> points
> >> to an array.

I don't know what definition you are talking about, but either the
definition, or your interpretation thereof, is wrong.

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

The definition in the C++ standard says it points to the first element OF AN
ARRAY.
therefore by definition it points to an array you idiot.


<snip >


cg_chas

unread,
Mar 31, 2011, 6:13:39 AM3/31/11
to
On Thu, 31 Mar 2011 10:52:48 +0100, "Paul" <pchr...@yahoo.co.uk> wrote:

>
>"Goran" <goran...@gmail.com> wrote in message
>news:362fae78-1af4-4f00...@k22g2000yqh.googlegroups.com...
>On Mar 31, 3:22 am, "Paul" <pchris...@yahoo.co.uk> wrote:
>> >>>> Yes says the proven idiot who thinks p doesn't point to an array
>> >>>> with:
>> >>>> int* p = new int[5]
>>
>> >>> p is not a pointer to an array; p is a pointer to an int.
>> >> No p points to the initial element *of an array*, by definiton it
>> >> points
>> >> to an array.
>
>I don't know what definition you are talking about, but either the
>definition, or your interpretation thereof, is wrong.
>
>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
>
>The definition in the C++ standard says it points to the first element

stop right there and you'll seem like less of a degenerate.

>OF AN ARRAY.
Pointing to the first element is not the same thing as pointing to the array.
The array is a different type than is the first element, no matter how many
times you beligerantly say otherwise.

>therefore by definition it points to an array you idiot.

lol, by your definition, which everybody who has responded to you has indicated
is meaningless.

your points are all meaningless paul. congratulations for all your time well
spent :)

Goran

unread,
Mar 31, 2011, 7:00:16 AM3/31/11
to
On Mar 31, 11:52 am, "Paul" <pchris...@yahoo.co.uk> wrote:
> The definition in the C++ standard says it points to the first element OF AN
> ARRAY.
> therefore by definition it points to an array you idiot.

First part, I agree. Second part (the "therefore" one), is false (and
is not in the standard, either).

Here, a practical example why __your__ "therefore" is wrong:

class A
{
public:
A() : i(0) {}
const int i;
};

class B : public A
{
public:
B() : j(1) {}
const int j;
};

int main(int, char*[])
{
const B b[2];
const A* a = b;
if (a->i == 0)
std::cout << "a points to the array b" << std::endl;
a++;
std::cout << "I did a++; now it points to the second element of the
array b;" << std::endl;
std::cout << "That's what pointers do, right?" << std::endl;
if (a->i == 1)
{
std::cout << "Hmmm... no object of type A has i that equals 1." <<
std::endl;
std::cout << "I must have invoked UB somewhere. I wonder where..."
<< std::endl;
std::cout << "Perhaps in the part where I said that a points to
the array b?" << std::endl;
std::cout << "Nooo... Un-possible!";
}
return 0;
}

Goran.

SG

unread,
Mar 31, 2011, 7:46:50 AM3/31/11
to
On 31 Mrz., 08:31, Goran wrote:
> [...]

> The problem is elsewhere: when you do "new TYPE[size1][size2]",
> the type of result is "TYPE**",

No, it is not. The type of this new expression is TYPE(*)[size2]
(assuming TYPE is not an array-type).

On 31 Mrz., 11:52, Paul wrote:
> [...]


> The definition in the C++ standard says it points to the first element

> OF AN ARRAY. therefore by definition it points to an array [...]

Wow. Apparently, the discussion is still about the banana vs bunch of
bananas thing. I still see no definition of the word "pointer" or the
expression "points to X" in the C++ ISO standard that would justify
your use of the words "therefore by definition" in this context.
Consider the possibility that you are (perhaps unintentionally)
augmenting the standard's text with your personal understanding of
what "points to X" means exactly.

Regardless of the interpretation of "points to X", an array is not a
pointer. Since you evaded revisiting this claim of yours in favour of
this stupid discussion about the semantics of "points to X", my
conclusion is you are too proud to admit that you were wrong about the
"an array is just a pointer" issue.

SG

Leigh Johnston

unread,
Mar 31, 2011, 8:04:41 AM3/31/11
to

By whose definition? Yours? Your own personal definitions of things
carry no weight here. The fact that p points to the initial element of
an array does not mean that p is a pointer to an array; p is a pointer
to an int.

> Were you born stupid or did you grow into it?

Occam's Razor my dear chap: which is more likely: everybody except Paul
is stupid or just Paul is stupid?

/Leigh

Goran

unread,
Mar 31, 2011, 8:16:58 AM3/31/11
to
On Mar 31, 1:46 pm, SG <s.gesem...@gmail.com> wrote:
> On 31 Mrz., 08:31, Goran wrote:
>
> > [...]
> > The problem is elsewhere: when you do "new TYPE[size1][size2]",
> > the type of result is "TYPE**",
>
> No, it is not. The type of this new expression is TYPE(*)[size2]
> (assuming TYPE is not an array-type).

Whoops, indeed. Heat of the discussion ;-) ...

Goran.

Paul

unread,
Mar 31, 2011, 9:14:30 AM3/31/11
to

"Goran" <goran...@gmail.com> wrote in message
news:b5b52d80-6f54-440d...@s18g2000prg.googlegroups.com...

On Mar 31, 11:52 am, "Paul" <pchris...@yahoo.co.uk> wrote:
> The definition in the C++ standard says it points to the first element OF
> AN
> ARRAY.
> therefore by definition it points to an array you idiot.

First part, I agree. Second part (the "therefore" one), is false (and
is not in the standard, either).

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

It IS the defintioon in the standard, the standard states it points to the
first element OF AN ARRAY, therefore it cannot NOT point to an array.

The standard certainly doesn't state, that it doesn't point to an array, as
you are saying.
You do not accept the opinion of experts who say that a T* can point to a T,
or an array of T's.


<snip>

Paul

unread,
Mar 31, 2011, 9:16:18 AM3/31/11
to

"Leigh Johnston" <le...@i42.co.uk> wrote in message
news:24-dnUMwk6tF8AnQ...@giganews.com...

> On 31/03/2011 02:22, Paul wrote:
>>
>> "Leigh Johnston" <le...@i42.co.uk> wrote in message
>> news:6ZqdnRJoifyzXw7Q...@giganews.com...
>>> On 31/03/2011 00:42, Paul wrote:
>>> [...]
>>>>>>> Anyway it doesn't matter how it *seems* to you; what is important is
>>>>>>> to be technically accurate and to use correct terminology: casting
>>>>>>> from derived to base is called "upcasting"; casting from base to
>>>>>>> derived is called "downcasting".
>>>>>>>
>>>>>> Yes says the proven idiot who thinks p doesn't point to an array
>>>>>> with:
>>>>>> int* p = new int[5]
>>>>>
>>>>> p is not a pointer to an array; p is a pointer to an int.
>>>> No p points to the initial element *of an array*, by definiton it
>>>> points
>>>> to an array.
>>>
>>> Whilst p does point to the initial element of an array that does not
>>> mean that p is a pointer to an array; p is a pointer to an int.
>>>
>> If p points to the intial element *OF AN ARRAY*, then by defintion it
>> points to an array.
>
> By whose definition? Yours?
By the defintion of the C++ standards, that state the pointer points to the
first element OF AN ARRAY.
It can't not point to an array if it points to the first element OF AN
ARRAY, you idiot.

Leigh Johnston

unread,
Mar 31, 2011, 9:26:30 AM3/31/11
to

You are just going round in circles. Again: there is a difference
between the not so technical term "points to" and the technical term "a
pointer to".

A *pointer to an int* is *a pointer to an int* not *a pointer to an
array*; pretty simple IMO so I wonder why you don't "get" it.

/Leigh

Paul

unread,
Mar 31, 2011, 9:28:51 AM3/31/11
to

"SG" <s.ges...@gmail.com> wrote in message
news:116c937b-de2e-44a4...@f30g2000yqa.googlegroups.com...

> On 31 Mrz., 08:31, Goran wrote:
>> [...]
>> The problem is elsewhere: when you do "new TYPE[size1][size2]",
>> the type of result is "TYPE**",
>
> No, it is not. The type of this new expression is TYPE(*)[size2]
> (assuming TYPE is not an array-type).
>
> On 31 Mrz., 11:52, Paul wrote:
>> [...]
>> The definition in the C++ standard says it points to the first element
>> OF AN ARRAY. therefore by definition it points to an array [...]
>
> Wow. Apparently, the discussion is still about the banana vs bunch of
> bananas thing. I still see no definition of the word "pointer" or the
> expression "points to X" in the C++ ISO standard that would justify
> your use of the words "therefore by definition" in this context.
> Consider the possibility that you are (perhaps unintentionally)
> augmenting the standard's text with your personal understanding of
> what "points to X" means exactly.
>
No I agree the majority of experts who also say a pointer of type T* can
point to a T , or an array of T's.
Its the people here who are saying that T* does not point to an array who
are making an idiotic and nonsensical statement that goes against the common
understanding. The burden of proof lies with them/YOU.


> Regardless of the interpretation of "points to X", an array is not a
> pointer. Since you evaded revisiting this claim of yours in favour of
> this stupid discussion about the semantics of "points to X", my
> conclusion is you are too proud to admit that you were wrong about the
> "an array is just a pointer" issue.
>

This is absolute bollocks , I never said an array was the same as a pointer,
I say that in some situations it is, for all intensive purposes, the same.
Now you say you know more about my views than I do? Go to France you fin
idiot.


Paul

unread,
Mar 31, 2011, 9:37:12 AM3/31/11
to

"Leigh Johnston" <le...@i42.co.uk> wrote in message
news:ecidnQ_9haKbHAnQ...@giganews.com...
And a pointer to an array of int is a pointer to an array.
This is a pointer to an array , not a pointer to a single int, pretty
simple:
int* p = new int[6];

You obviously have an overwhelming desire to get your own back after the
many times i have proved you wrong. I have won this argument arleady and I
see no need to reply to your idiotic nonsense anymore.

Leigh Johnston

unread,
Mar 31, 2011, 9:44:52 AM3/31/11
to

Indeed; nobody said otherwise.

> This is a pointer to an array , not a pointer to a single int, pretty
> simple:
> int* p = new int[6];

p is a pointer to an int not a pointer to an array; you can bleat that
this is incorrect as much as you like but it will not change the fact
that it is a correct statement.

>
> You obviously have an overwhelming desire to get your own back after the
> many times i have proved you wrong. I have won this argument arleady and
> I see no need to reply to your idiotic nonsense anymore.
>

Get my own back? Why? You have not proven me or anybody else wrong so
far. If you ever do prove me wrong about something I will admit my
mistake; I certainly wouldn't want to "get my own back". Also: the ad
hominem is a logical fallacy.

/Leigh

Goran

unread,
Mar 31, 2011, 10:01:25 AM3/31/11
to
On Mar 31, 3:14 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> "Goran" <goran.pu...@gmail.com> wrote in message

First things first. You do understand now that casts you tried to pull
off are UB, right?

Goran.

Goran

unread,
Mar 31, 2011, 10:21:39 AM3/31/11
to
On Mar 31, 3:14 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> "Goran" <goran.pu...@gmail.com> wrote in message

OK, so, let's say that what you say is true... (proof by contradiction
follows...)

In my previous example... What does "a" in "const A* a = b" points to
then? Clearly, b is an array. So what does a points to? To an array of
A, an array of B, or what? Clearly, b is an array, code is legal, no
casting, no funny business...

Further, if a points to an array of A, why incrementing it gives
strange results? If it's an array of B, how can that even compile? (B
__is__ A, but A __is not__ B).

I know that you have no relevant answer to any of these questions, so
I'll give it to you: "a" points to __the first element of "b"__. It
points to no array, ever.

Goran.

Paul

unread,
Mar 31, 2011, 10:55:33 AM3/31/11
to

"Goran" <goran...@gmail.com> wrote in message
news:5e510662-7f68-438d...@1g2000yqq.googlegroups.com...

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

What exactly is UB? Casting in general produces UB, or only when I cast?

Is it a case that you are not interested in discovering the true language
technicalities and that your sole intention is to prove that I am wrong
about something.

Goran

unread,
Mar 31, 2011, 11:10:50 AM3/31/11
to
On Mar 31, 4:55 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> 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).

Goran.

SG

unread,
Mar 31, 2011, 12:01:10 PM3/31/11
to
On 31 Mrz., 15:28, "Paul" <pchris...@yahoo.co.uk> wrote:
> This is absolute bollocks , I never said an array was the same as a pointer,

I quoted you correctly. You said "an array is just a pointer". You
used this as subject to one of the threads that spawned over 200 other
posts.

> I say that in some situations it is, for all intensive purposes, the same.

An array is never a pointer. What you tried to say should have been
worded like this: One can use an array expression in contexts where a
pointer is required due to the array-to-pointer standard conversion.
That's about it. You're just being overly broad and imprecise, as
ever. If you want to avoid looking dumb, you should put a little more
effort into precise wording.

Also, it strikes me as odd that a presumably native English speaker
who claims to be smarter than everybody who disagrees with him in here
says "intensive purposes" when "intents and purposes" is what he
meant.

> Go to France you fin idiot.

Oh, how could I forget the name calling. Yes, that's definitely
indicating cleverness.

SG

Paul

unread,
Mar 31, 2011, 1:20:58 PM3/31/11
to

"Goran" <goran...@gmail.com> wrote in message
news:c59c6538-f590-41aa...@1g2000yqq.googlegroups.com...

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

You haven't proved anything is UB, In C++ casting is not UB , its
conversion form one type to another. Initially you said casting the return
from new was UB but since I have stated the standards states the return from
new must be castable you have changed your tune to , "your cast is UB
because I say so". Your code with assets and comparisons does not prove that
a cast is UB it only proves you can write code that has bugs.

Are you saying that casting a pointer to an array is UB? , Who knows because
you are not being specific, you are simply stating my cast is UB because you
say so.

Is this UB in your mind then:

template <typename T, int S>
T* foo(){
return static_cast<T*>(::operator new(S * sizeof(T)));
}

int main() {
int (*p)[6] = foo<int[6], 6>();
}

.


Paul

unread,
Mar 31, 2011, 1:23:58 PM3/31/11
to

"SG" <s.ges...@gmail.com> wrote in message
news:99e47923-2e97-4a52...@hd10g2000vbb.googlegroups.com...

> On 31 Mrz., 15:28, "Paul" <pchris...@yahoo.co.uk> wrote:
>> This is absolute bollocks , I never said an array was the same as a
>> pointer,
>
> I quoted you correctly. You said "an array is just a pointer". You
> used this as subject to one of the threads that spawned over 200 other
> posts.
>

You do not define what I say , I do.

Peter Remmers

unread,
Mar 31, 2011, 3:32:30 PM3/31/11
to
Am 31.03.2011 18:01, schrieb SG:
> Also, it strikes me as odd that a presumably native English speaker
> who claims to be smarter than everybody who disagrees with him in here
> says "intensive purposes" when "intents and purposes" is what he
> meant.

*facepalm*

I kept wondering what was so intensive about the purposes...

Peter

Leigh Johnston

unread,
Mar 31, 2011, 3:37:33 PM3/31/11
to

lulz.

/Leigh

cg_chas

unread,
Mar 31, 2011, 4:13:07 PM3/31/11
to
On Thu, 31 Mar 2011 21:32:30 +0200, Peter Remmers
<p.re...@expires-2011-04-30.arcornews.de> wrote:

lol, priceless

Paul

unread,
Mar 31, 2011, 4:28:41 PM3/31/11
to

"Peter Remmers" <p.re...@expires-2011-04-30.arcornews.de> wrote in message
news:4d94d6d5$0$6987$9b4e...@newsspool4.arcor-online.net...
Well keep on wondering maybe one day you will understand.

Peter Remmers

unread,
Mar 31, 2011, 4:55:22 PM3/31/11
to

I guess your repetitive misuse of that expression shows that you
literally "don't know what you're talking about", i.e. what the words
you fail to use actually mean.

I bet you're one of those who don't get there/their/they're right.

Your response only shows that you are unable to own up to your mistakes.

Peter

Paul

unread,
Mar 31, 2011, 6:06:56 PM3/31/11
to

"Peter Remmers" <p.re...@expires-2011-04-30.arcornews.de> wrote in message
news:4d94ea41$0$6975$9b4e...@newsspool4.arcor-online.net...
It wasn't a mistake its a deliberate varaition, unlike your misunderstanding
of C++.

Leigh Johnston

unread,
Mar 31, 2011, 6:43:23 PM3/31/11
to

Admit to your mistakes you liar.

/Leigh

Drew Lawson

unread,
Mar 31, 2011, 7:08:41 PM3/31/11
to
In article <4d94d6d5$0$6987$9b4e...@newsspool4.arcor-online.net>

Intent sieve porpoises?

The very idea is full of holes.

--
Drew Lawson I had planned to be dead by now, but
the schedule slipped, they do that.
-- Casady

Ian Collins

unread,
Mar 31, 2011, 7:12:36 PM3/31/11
to

A friend just posted this link on another group:

http://www.politicsforum.org/images/flame_warriors/flame_77.php

I though it apt here as well.

--
Ian Collins

Goran

unread,
Apr 1, 2011, 4:14:23 AM4/1/11
to
On Mar 31, 7:20 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> "Goran" <goran.pu...@gmail.com> wrote in message

>
> news:c59c6538-f590-41aa...@1g2000yqq.googlegroups.com...
> On Mar 31, 4:55 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
>
> > 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

Now... (proof by contradiction follows... Do you know what "proof by
contradiction" means, BTW? I hope so. If not, I hope you can google
it.)

So... See the code? See the line:

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

?

You claimed that one should be able to do it, in this post:
http://groups.google.com/group/comp.lang.c++/msg/310cebb655d59715

So, presuming that your cast is not UB, I made you a bit of code that
uses your cast and doesn't work correctly. I'll repeat offending part,
slightly modified, since you seem to have an issue with assert macro
(a macro is not a statement, which is something you don't seem to
understand well):

Base (*p2)[3] = (Base (*)[3])new Derived[2][3]; // Presumption: no UB
in cast.
const Base& b = p2[0][1];
if (b.i) std::cout << "This is not possible!";

I'll also show you the correct code:

Derived(*p2)[3] = new Derived[2][3];
const Base& b = p2[0][1];
if (b.i) std::cout << "This is not possible!";

Contradiction is: the only difference between these two snippets is
the the cast^^^. If there's no UB in the cast, why doesn't first
snippet work? Answer: cast is UB; by consequence, anything that
follows is wrong.

^^^ Bar the use of Base type. But since e.g. "Base (*p2)[3] = new
Derived[2][3];" doesn't even compile, that's immaterial.

Goran.

Paul

unread,
Apr 1, 2011, 6:53:19 AM4/1/11
to

"Goran" <goran...@gmail.com> wrote in message
news:b371e97b-2d73-4cb0...@r13g2000yqk.googlegroups.com...

On Mar 31, 7:20 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> "Goran" <goran.pu...@gmail.com> wrote in message
>
> news:c59c6538-f590-41aa...@1g2000yqq.googlegroups.com...
> On Mar 31, 4:55 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
>
> > 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. You cannot even explain what
is wrong with the cast in your opinion , its just wrong?

I provided the following code as an alternative which you snipped and
ignored. And you replaced it with your buggy shit 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*>(::operator new(S * sizeof(T)));
}
int main() {
int (*p)[6] = foo<int[6], 6>();
}

<Snip>

Paul

unread,
Apr 1, 2011, 7:52:58 AM4/1/11
to

"Goran" <goran...@gmail.com> wrote in message
news:b371e97b-2d73-4cb0...@r13g2000yqk.googlegroups.com...

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

?

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

This is because you think that the pointer-type Base (*)[3], points to an
array of Base[3], but it doesn't it points to an array of Derived[3].

Its your code that is wrong because you derefernce p2 as if it were a Base,
but it points to a Derived.
p2[i] returns i*sizeof(Base[3]), this is not the same as
i*sizeof(Derived[3]).

The memory layout of the object array is as follows:
[[Base][Derived]] [[Base][Derived]] [[Base][Dervied]]

You are trying to index this array in chunks sizeof(Base[3]).

This example to shows that the pointer-type does not define the object it
points to.
p2 points to an array of Derived, not an array of Bases.


Goran

unread,
Apr 1, 2011, 8:11:29 AM4/1/11
to
On Apr 1, 12:53 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> "Goran" <goran.pu...@gmail.com> wrote in message
>
> news:b371e97b-2d73-4cb0...@r13g2000yqk.googlegroups.com...
> On Mar 31, 7:20 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
>
>
>
> > "Goran" <goran.pu...@gmail.com> wrote in message
>
> >news:c59c6538-f590-41aa...@1g2000yqq.googlegroups.com...
> > On Mar 31, 4:55 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
>
> > > 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*>(::operator 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:

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.

Goran.

Goran

unread,
Apr 1, 2011, 8:36:48 AM4/1/11
to
On Apr 1, 12:53 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
> "Goran" <goran.pu...@gmail.com> wrote in message
>
> news:b371e97b-2d73-4cb0...@r13g2000yqk.googlegroups.com...
> On Mar 31, 7:20 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
>
>
>
> > "Goran" <goran.pu...@gmail.com> wrote in message
>
> >news:c59c6538-f590-41aa...@1g2000yqq.googlegroups.com...
> > On Mar 31, 4:55 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
>
> > > 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. You cannot even explain what
> is wrong with the cast in your opinion , its just wrong?

Being polite when asking for help is somewhat better. You might want
to try e.g. this way:

"I don't understand compiler errors. I did ABC, compiler told me XYZ.
What should I do?"

Goran.

It is loading more messages.
0 new messages