In-memory construction of variant types/subclasses?

  • Thread starter Ulrich Hobelmann
  • Start date
U

Ulrich Hobelmann

Hi, slowly transitioning from C to C++, I decided to remodel a
struct/union (i.e. type identifier as first field, union of variant
types) as a class + subclasses. Switching functions are replaced by
virtual functions. So far so good.

Now what I used to do is have a struct, set its type and union member,
and return a pointer. I.e. I initialized the struct appropriately and
returned a reference. Now I'd like to do that in C++ (right now I
construct a new subclass with "new" and delete it after every call,
because the instance is only needed very shortly anyway; seems ugly to me).

I tried to define a union that contains all subclasses (that I will ever
use) of the base class, but C++ complains that it can't have objects
with constructors or destructors inside a union.

Is there any way to have a static piece of storage, and to return
references/objects(by value) or pointers to this piece of storage, while
also initializing it (i.e. myunion.objectB = ObjectB(); return
myunion.objecTB; or something like that)? In C I didn't need malloc()
in this case; I don't see why I should need new() now.
 
S

stefan.ciobaca

Could you please give some supporting code?
I'm afraid I couldn't follow what you're saying (starting from
the 2nd paragraph), even though I read the thing at least 3
times ;-)
 
J

Jerry Coffin

[ ... ]
Is there any way to have a static piece of storage, and to return
references/objects(by value) or pointers to this piece of storage, while
also initializing it (i.e. myunion.objectB = ObjectB(); return
myunion.objecTB; or something like that)? In C I didn't need malloc()
in this case; I don't see why I should need new() now.

Yes -- it's called placement new. You do something like:

static char buffer[4096]; // assume that's big enough...

your_class *object = new(buffer) your_class;

When you're done with this object, you don't delete it -- instead,
you call its dtor directly:

object->~your_class();

As far as being anything like malloc goes: no, it's not. malloc does
one thing: allocates raw memory. The usual use of new does two
things: allocates some memory (about like malloc), and then creates
an object in that memory.

Placement new does only the _second_ part of that. It doesn't
allocate any memory -- it just creates an object in the memory you
designate. You're still creating a new object, so (at least to me) it
makes perfect sense to use the "new" keyword, even though you're not
doing anything that corresponds to what malloc does.
 
M

Moonlit

Hi,

Yes, look up 'in place new' on parashift.

Here is a piece of my Variant type code:

// in the header
union {
Int8 Char;
Int64 Long;
UInt8 UChar;
UInt64 ULong;
double Double;
bool Bool;
char String [ sizeof( std::string ) ];
char Map [ sizeof( std::map<UVar*,UVar*, UFindVar> ) ];
char SRefPtr[ sizeof( MSRefPtr<ISerialize> ) ];
char WRefPtr[ sizeof( MWRefPtr<ISerialize> ) ];
char KeyStroke[ sizeof( MKey ) ];
};

And then in the implementation if the variant is for instance string: (from
a piece of the copy constructor passed variable Var)

case eString:
new( this->String ) string( *reinterpret_cast<string const *const>(
Var.String ) );
break;

--
Make sure to set the alignment options for your compiler otherwise maybe
stuff could get misaligned i.e. on char istead of four byte boundary.

Regards, Ron AF Greve

http://moonlit.xs4all.nl
 
U

Ulrich Hobelmann

Could you please give some supporting code?

I have a function that will return one of many subclasses of a base
class (so it can't be call-by-value, because the subclasses can have
different sizes). I don't want to use new(), because the object is only
used for a very short time. In C I simply had a union of appropriate
types, initialized one of them, and returned a pointer. In C++ I'd like
to return a reference (ok, doesn't matter really), but the union can't
contain a list of my subclasses, due to init/destruction issues it seems.

Jerry and Moonlit, thanks for the pointers. I could use placement new
(though it remains open how best to declare the memory area; A union
would free me from the chore of having to determine how big my objects
actually are), but I was completely ignoring that objects could have
destructors (ok, these don't, but still the idea seems a bit ugly).

I guess I'll just continue to go with new/delete. The few cycles
shouldn't hurt.
 
T

Thomas J. Gritzan

Ulrich said:
Hi, slowly transitioning from C to C++, I decided to remodel a
struct/union (i.e. type identifier as first field, union of variant
types) as a class + subclasses. Switching functions are replaced by
virtual functions. So far so good.

You could try the placement-new way, but others have done it before:

http://www.boost.org/doc/html/variant.html

Thomas
 
J

Jerry Coffin

Jerry Coffin posted:

static char buffer[4096]; // assume that's big enough...

That's not guaranteed to be suitably aligned.

True -- a bit of ugliness to attempt to keep the code as simple as
possible, and concentrate on the placement new part. You're right,
however, that I probably should have pointed out the limitations more
thoroughly. OTOH, hopefully the comment was enough to indicate that
this buffer was really only for demo, not real use...
 
F

Frederick Gotham

Jerry Coffin posted:
Jerry Coffin posted:

static char buffer[4096]; // assume that's big enough...

That's not guaranteed to be suitably aligned.

True -- a bit of ugliness to attempt to keep the code as simple as
possible, and concentrate on the placement new part. You're right,
however, that I probably should have pointed out the limitations more
thoroughly. OTOH, hopefully the comment was enough to indicate that
this buffer was really only for demo, not real use...


Yes I see what you're getting at, try to keep the example as simple as
possible.

I myself like to throw in a little comment, maybe at that point in the
code, or perhaps afterwards down before my signature, something like:

static char buffer[64]; /* Let's pretend it's suitably aligned */


It's good to be pedantic.
 

Ask a Question

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

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

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top