Qt-interest Archive, September 1999
arrays of objects in C++
Message 1 in thread
Hello Qtīers,
Please excuse me, this is not a Qt question, more a C++ question or a HP
aCC compiler bug report. I donīt know yet. One could also take it as a
hint for writing portable code. For me itīs basically the question
whether I have to rearrange code or to patch the compiler.
Assume an object for which thereīs no reasonable default constructor
(e.g. a Qt widget :-) ).
I want to create an Array of objects (a linear sequence of objects in
memory to which I could apply pointer arithmetics).
Class *p = new Class[ sz ]; would require the default constructor which
is by proposition not given.
Usually I did the following (Stanley B. Lippmann, C++ Primer, page 288):
I defined 2 template functions in my personal allocate.h
#include <new.h>
template <class Type>
void allocate( Type*& p, int sz )
{
p = new char[ sz * sizeof( Type ) ];
}
template <class Type>
void deallocate( Type*& p, int sz )
{
for ( long i = 0; i < sz; ++i )
( p + i )->Type::~Type();
delete ( char* )p;
}
In the main code I wrote (typically in a constructor)
#include <allocate.h>
Class *p;
allocate( p, sz );
for ( long i = 0; i < sz; ++i )
new( p + i ) Class( ArgumentList );
and (typically in the destructor)
deallocate( p, sz );
HP aCC-1.21 does not accept the code egcs-1.1 or aCC-1.12 do. Is it
valid memory management according to the final standard of C++? In most
cases I would not need the linear ordering in memory. But providing a
default constructor for every class would not only add runtime overhead
due to unnecessary copying, but also undermine the concept of
constructors, which are meant for generating objects with a resonable
initial state.
Message 2 in thread
On Tue, 7 Sep 1999, Stefan Link wrote:
> Hello Qtīers,
>
> Please excuse me, this is not a Qt question, more a C++ question or a HP
> aCC compiler bug report. I donīt know yet. One could also take it as a
> hint for writing portable code. For me itīs basically the question
> whether I have to rearrange code or to patch the compiler.
>
> Assume an object for which thereīs no reasonable default constructor
> (e.g. a Qt widget :-) ).
>
> I want to create an Array of objects (a linear sequence of objects in
> memory to which I could apply pointer arithmetics).
>
> Class *p = new Class[ sz ]; would require the default constructor which
> is by proposition not given.
>
> Usually I did the following (Stanley B. Lippmann, C++ Primer, page 288):
>
> I defined 2 template functions in my personal allocate.h
>
> #include <new.h>
>
> template <class Type>
> void allocate( Type*& p, int sz )
> {
> p = new char[ sz * sizeof( Type ) ];
> }
This is really ugly, but I guess if you don't have a default constructor
this is what you have to do. I guess the trick here is that you allocate
memory pointed to by p big enough to hold sz Types
> template <class Type>
> void deallocate( Type*& p, int sz )
> {
> for ( long i = 0; i < sz; ++i )
> ( p + i )->Type::~Type();
>
> delete ( char* )p;
> }
>
> In the main code I wrote (typically in a constructor)
>
> #include <allocate.h>
>
> Class *p;
>
> allocate( p, sz );
> for ( long i = 0; i < sz; ++i )
> new( p + i ) Class( ArgumentList );
I don't know this syntax, but it looks to me like you are allocating
memory twice. Since you allocated the memory above, why can't you use
p[i] = Class( ArgumentList );
or if assignment is not possible do
set(p+i,Class( ArgumentList );
Where
template<Type>void set(Type* p, Type* q)
{
memcpy(p,q,sizeof(Type);
}
----
This is all really ugly. In cases where a default constructor is not
available, I use a PointerArray template that does all what Array does,
but only operates on pointers, not the actual objects. You have to keep
straight if PointerArray deletes the objects when it is deleted, or
whether you have to do it yourself.
In commonly used objects, when I have a class foo, I often define a class
foos that is an array of class foo. I then make it so that there is an
"add" method in foos that you feed parameters of type foo and it
constructs one and adds it to the array. If you use this a lot, the extra
work initially is worth it.
Regards
Willem
================================================================
Dr. Willem A. Schreuder, Senior Engineer, Principia Mathematica
Address: 405 Urban Street, Suite 305, Lakewood, CO 80228, USA
Tel: (303) 716-3573 Fax: (303) 716-3575
WWW: www.prinmath.com Email: Willem.Schreuder@prinmath.com
Message 3 in thread
- Subject: Re: arrays of objects in C++
- From: "Fraser Hutchinson" <fraser@xxxxxx>
- Date: Tue, 7 Sep 1999 20:08:03 -0800
- Cc: qt-interest@xxxxxxxx
- Comments: Sender has elected to use 8-bit data in this message. If problems arise, refer to postmaster at sender's site.
- Organization: yeah, right, me organized?
- Priority: normal
- To: Willem Schreuder <willem@xxxxxxxxxxxx>
Date sent: Tue, 7 Sep 1999 14:20:48 -0600 (MDT)
From: Willem Schreuder <willem@prinmath.com>
To: Stefan Link <link@biomag5.zibmt.uni-ulm.de>
Copies to: qt-interest@troll.no
Subject: Re: arrays of objects in C++
Use placement new() - I think that will do the trick.
But it is a question of policy: for mecahnism, if you want to be able
to create an array of objects, either you will have to create them
using default constructors and intialize them after creation, or by
using placement new, or by hacking some unheard of scheme to
somehow call constructors in a new[] that allow for parameter
passing.
I would not even know how to approach the latter.
However, regardless of how you do it, allocating an array of objects
will ALWAYS require some explicit intialization of that object AFTER
the allocation, regardless of whether this is done via your hack
below, or by using default constructors and manually initializing
them.
If you REALLY must depend upon the intialization being performed
by the constructor, placement new is the only way I know of.
If I am missing something, please feel free to illuminate me!
Fraser
>
On Tue, 7 Sep 1999, Stefan Link wrote:
>
> > Hello Qtīers,
> >
> > Please excuse me, this is not a Qt question, more a C++ question or a HP
> > aCC compiler bug report. I donīt know yet. One could also take it as a
> > hint for writing portable code. For me itīs basically the question
> > whether I have to rearrange code or to patch the compiler.
> >
> > Assume an object for which thereīs no reasonable default constructor
> > (e.g. a Qt widget :-) ).
> >
> > I want to create an Array of objects (a linear sequence of objects in
> > memory to which I could apply pointer arithmetics).
> >
> > Class *p = new Class[ sz ]; would require the default constructor which
> > is by proposition not given.
> >
> > Usually I did the following (Stanley B. Lippmann, C++ Primer, page 288):
> >
> > I defined 2 template functions in my personal allocate.h
> >
> > #include <new.h>
> >
> > template <class Type>
> > void allocate( Type*& p, int sz )
> > {
> > p = new char[ sz * sizeof( Type ) ];
> > }
>
> This is really ugly, but I guess if you don't have a default constructor
> this is what you have to do. I guess the trick here is that you allocate
> memory pointed to by p big enough to hold sz Types
>
> > template <class Type>
> > void deallocate( Type*& p, int sz )
> > {
> > for ( long i = 0; i < sz; ++i )
> > ( p + i )->Type::~Type();
> >
> > delete ( char* )p;
> > }
> >
> > In the main code I wrote (typically in a constructor)
> >
> > #include <allocate.h>
> >
> > Class *p;
> >
> > allocate( p, sz );
> > for ( long i = 0; i < sz; ++i )
> > new( p + i ) Class( ArgumentList );
>
> I don't know this syntax, but it looks to me like you are allocating
> memory twice. Since you allocated the memory above, why can't you use
> p[i] = Class( ArgumentList );
> or if assignment is not possible do
> set(p+i,Class( ArgumentList );
> Where
> template<Type>void set(Type* p, Type* q)
> {
> memcpy(p,q,sizeof(Type);
> }
>
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Fraser Hutchinson fraser@aa.net
Seattle, Washington
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Message 4 in thread
#if Stefan Link
> HP aCC-1.21 does not accept the code egcs-1.1 or aCC-1.12 do. Is it
> valid memory management according to the final standard of C++? In most
> cases I would not need the linear ordering in memory. But providing a
> default constructor for every class would not only add runtime overhead
> due to unnecessary copying, but also undermine the concept of
> constructors, which are meant for generating objects with a resonable
> initial state.
AFAIK all QWidget derived classes have reasonable default constructors.
Is there a good reason to break C++ completely ? Why can't you just make
a QArray of QWidget * ?
Cheers,
Rik