469,291 Members | 1,701 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,291 developers. It's quick & easy.

Variably sized instances of a class

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.
Jul 20 '06 #1
7 1041
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
---------

"Ole Nielsby" <ol*********@snailmail.dkwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
>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.


Jul 21 '06 #2
"G Himangi" <in**@ssware.comwrote in message
news:uI**************@TK2MSFTNGP03.phx.gbl...
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 Qclass myClass
{
private:
char data[Q];
public:
myClass()
{
}
//other stuff
};

myClass<100anInstance();

--

Kind regards,
Bruno van Dooren
br**********************@hotmail.com
Remove only "_nos_pam"
Jul 21 '06 #3
G Himangi <in**@ssware.comwrote:
Ole Nielsby <ol*********@snailmail.dkwrote:
>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?
Jul 21 '06 #4

Ole Nielsby wrote:
G Himangi <in**@ssware.comwrote:
Ole Nielsby <ol*********@snailmail.dkwrote:
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

Jul 21 '06 #5
>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.
--
Vladimir Nesterovsky
Jul 21 '06 #6

<ad******@club-internet.frwrote:
>
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.
>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.
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
Jul 21 '06 #7

"Ole Nielsby" <ol*********@snailmail.dka écrit dans le message de news:
uE**************@TK2MSFTNGP04.phx.gbl...
>
<ad******@club-internet.frwrote:
>>
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.
>>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.

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-lit...html#faq-11.14

Arnaud
MVP -VC
Jul 22 '06 #8

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

7 posts views Thread by Kerry Neilson | last post: by
4 posts views Thread by Piotr Sawuk | last post: by
90 posts views Thread by Ben Finney | last post: by
5 posts views Thread by Lyle Avery | last post: by
10 posts views Thread by Karlo Lozovina | last post: by
33 posts views Thread by Peng Yu | last post: by
44 posts views Thread by Steven D'Aprano | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by harlem98 | last post: by
1 post views Thread by Geralt96 | last post: by
reply views Thread by harlem98 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.