Variably sized instances of a class

O

Ole Nielsby

I want to create a class with a variably-sized array inlined.
The array size will be known at each instantiation but not
at compile time. Once created, arrays won't grow or shrink
and their contents won't change.

The array length will be accessible via a smart pointer
located before the array. On destruction, it must be fetched
before the smartpointer containing it is destroyed.

The arrays will typically hold smart pointers, so proper
destruction is a must.

Is this feasible with C++?

Unfortunately, overloading new() won't do the trick unless
I resort to nasties such as passing the required extra byte
count in a TLS slot.
 
G

G Himangi

Thats not possible. The compiler must know at compile-time the exact size of
the every class - having variable sized inline arrays violates this.


---------
- G Himangi, Sky Software http://www.ssware.com
Shell MegaPack : Drop-In Explorer GUI Controls For Your Apps (.Net & ActiveX
Editions Available)
EZNamespaceExtensions.Net : Develop namespace extensions rapidly in .Net
EZShellExtensions.Net : Develop all shell extensions rapidly in .Net
 
B

Bruno van Dooren [MVP VC++]

G Himangi said:
Thats not possible. The compiler must know at compile-time the exact size
of the every class - having variable sized inline arrays violates this.

Except if you use a template class for this, and all array lengths are known
at compiletime.

something like

template <int Q> class myClass
{
private:
char data[Q];
public:
myClass()
{
}
//other stuff
};

myClass<100> anInstance();

--

Kind regards,
Bruno van Dooren
(e-mail address removed)
Remove only "_nos_pam"
 
O

Ole Nielsby

G Himangi said:
Ole Nielsby said:
I want to create a class with a variably-sized array inlined.
The array size will be known at each instantiation but not
at compile time. [...]

Is this feasible with C++?

Thats not possible. The compiler must know at compile-time
the exact size of the every class - having variable sized inline
arrays violates this.

"Not possible" is not a phrase in my vocabulary. I'm sure it is
possible, though it may violate some fundamentals of what is
considered sound C++ programming style.

I need it because my program will create millions of these
objects and the overhead of allocating separate array objects
is not acceptable.

So the question is really not "can I do it or not", but rather:
What's the best I can do to perform this hack and wrap it up
nicely?

If I can't create the objects with new , I can still use
malloc() or a homebrew memory manager to get memory
blocks of the needed size. Given a *void pointer, I can cast
it to *MyClass and initialize it. But how do I best perform
this initialization? By copy constructor? Assignment overload?
memcopying a stack allocated instance?

The class has virtual methods, so the vtable must be filled in.

I might need to forsake C++ destructors and define my own
destroy method and use a custom smart pointer template,
but this should still be possible, right???

Is it, by any chance, possible to call constructor methods
explicitly on an uninitialized memory block, and will this
initialize the vtable pointer? Or is there a way to explicitly
initialize it?
 
A

adebaene

Ole said:
G Himangi said:
Ole Nielsby said:
I want to create a class with a variably-sized array inlined.
The array size will be known at each instantiation but not
at compile time. [...]

Is this feasible with C++?

Thats not possible. The compiler must know at compile-time
the exact size of the every class - having variable sized inline
arrays violates this.

"Not possible" is not a phrase in my vocabulary. I'm sure it is
possible, though it may violate some fundamentals of what is
considered sound C++ programming style.

Most important, it violates the C++ standard, which means that whatever
solution you could devise, it may break on the next compiler release or
service pack, and would most probalby be not portable.

I need it because my program will create millions of these
objects and the overhead of allocating separate array objects
is not acceptable.
If you really create millions of object, I beg each array would be
quite small. Can't you fix an upper-bound to the array size and have
all instances use this max size?
So the question is really not "can I do it or not", but rather:
What's the best I can do to perform this hack and wrap it up
nicely?

If I can't create the objects with new , I can still use
malloc() or a homebrew memory manager to get memory
blocks of the needed size. Given a *void pointer, I can cast
it to *MyClass and initialize it. But how do I best perform
this initialization? By copy constructor? Assignment overload?
memcopying a stack allocated instance? placement-new.

The class has virtual methods, so the vtable must be filled in.

I might need to forsake C++ destructors and define my own
destroy method and use a custom smart pointer template,
but this should still be possible, right???
Maybe, but I definitely will not use this kind of hack in production
code...
Is it, by any chance, possible to call constructor methods
explicitly on an uninitialized memory block, and will this
initialize the vtable pointer? Or is there a way to explicitly
initialize it?
placement-new. However, it means you cannot instantiate the object on
the stack....

Arnaud
MVP - VC
 
V

Vladimir Nesterovsky

I want to create a class with a variably-sized array inlined.
The array size will be known at each instantiation but not
at compile time. Once created, arrays won't grow or shrink
and their contents won't change.

The array length will be accessible via a smart pointer
located before the array. On destruction, it must be fetched
before the smartpointer containing it is destroyed.

The arrays will typically hold smart pointers, so proper
destruction is a must.

Is this feasible with C++?

Unfortunately, overloading new() won't do the trick unless
I resort to nasties such as passing the required extra byte
count in a TLS slot.

You can overload "operator new". If you need define additional arguments in
that "operator new" (eg. new(param1, param2) A(x,y,z) ). Or you can create
"factory" function that allocates required space and calls placement "new"
to initialize instance. You have to compensate you allocation logic with
required deallocation logic.
 
O

Ole Nielsby

Most important, it violates the C++ standard, which means
that whatever solution you could devise, it may break on
the next compiler release or service pack, and would most
probalby be not portable.

"not portable" would mean, some of the code might have to
be rewritten for ports. If I wrap the dirty tricks in bag of
templates or whatever, I should be able to minimize the
rewriting to just that.
Can't you fix an upper-bound to the array size [...]

No. Most of them will be small - a few will be huge, and
I want non-virtual (inline) methods to work on both small
and large.
placement-new.

Thanks - this seems to be what I need.

Now, if I do a naive delete on a *MyClass created this way, am
I right in assuming that this will call the destructor of MyClass,
and after that, deallocate the memory?

If this is the case, things aren't too bad. The destructor will need
to destroy or zero any smart pointers contained in the array, which
shouldn't be too hard.

This will enable me to stick with a relatively standard coding style,
I'll just have to create the objects by means of factory methods
rather than new'ing them.

Regards/Ole Nielsby
 
A

Arnaud Debaene

Ole Nielsby said:
Most important, it violates the C++ standard, which means
that whatever solution you could devise, it may break on
the next compiler release or service pack, and would most
probalby be not portable.

"not portable" would mean, some of the code might have to
be rewritten for ports. If I wrap the dirty tricks in bag of
templates or whatever, I should be able to minimize the
rewriting to just that.
Can't you fix an upper-bound to the array size [...]

No. Most of them will be small - a few will be huge, and
I want non-virtual (inline) methods to work on both small
and large.
placement-new.

Thanks - this seems to be what I need.

Now, if I do a naive delete on a *MyClass created this way, am
I right in assuming that this will call the destructor of MyClass,
and after that, deallocate the memory?

No. You can't call delete on those objects. You must *explicitely* call the
destructor, then free the memory buffer by hand.

Note that if you overload placement-new for your class, you also must
provide a placement-delete operator, but it is used only if the
placement-new throws an exception. For a complete explanation, see
http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.14

Arnaud
MVP -VC
 

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

Top