Jump to content
  • Advertisement
Sign in to follow this  
kag1

A dynamic Array of Classes with Constructors [SOLVED]

This topic is 4920 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm wondering how I can achieve this...I know how to do this..
cClass * ArrayOfClasses;


//later on
ArrayOfClasses = new cClass[4];
but what if the class has a constructor that must be used..such as this
//What the Constructor looks like
cClass::cClass(LPDIRECT3DDEVICE9 Device);
Then how would I create my dynamic array of classes?
//Define my classes
cClass * ArrayOfClasses;

//would like to create a dynamic amount of classes now..
//this line doesn't work..
ArrayOfClasses = new cClass(g_Device)[4];
What is the correct Syntax for that? or do you just not do it? [Edited by - kag1 on April 26, 2005 11:34:58 PM]

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by kag1
What is the correct Syntax for that? or do you just not do it?


There are a thew ways, from bad to good:

1. you create a C-style dynamic array of pointers instead i.e:

foo** f = new foo*[size];

f[0] = new foo(/*...*/);
//...
delete f[0];
//....
delete[] f;

disadvantage extra level of indirection for no reason and memory is not contiguous any more.

2. you allocate a chunk of uninitialized memory then initialize each element i.e:


#include <new>

foo* f = static_cast<foo*>(::operator new(sizeof(foo) * size)); //allocates only!

::new(f[0]) foo(/*...*/); //called placement new, constructs only!
.....
f[0]->~foo(); // you must when using placement new, destructs only!
....
::operator delete(f); // deallocates only!


disadvantage it's to low-level & tedious potentially dangerous (you must explicitly invoke destructors when using placement new operator).

3. use C++ dynamic arrays i.e. std::vector

#include <vector>
std::vector<foo> v(size, foo(/*...*/));


no disadvantages.

[Edited by - snk_kid on April 26, 2005 6:46:18 PM]

Share this post


Link to post
Share on other sites
[edit]Boo for beating me. By the way, does std::vector require a default constructor? I suppose it just internally allocates bytes and uses placement new as well, though, so probably not. If that's the case, then yeah, I agree, use std::vector. I would've mentioned it before placement new, but I was thinking that it required the existence of a default constructor.[/edit]

Well, it wouldn't be as clean looking, but you could make use of the placement new operator. I haven't used it myself before, but I think I'm familiar enough to give you a piece of code that should supposedly work:

cClass *ArrayOfClass;

//Allocation
ArrayOfClasses = (cClass*)(new char[sizeof(cClass) * NumElements]);
for (int i = 0; i < NumElements; ++i)
new (ArrayOfClasses + i) cClass(g_Device);

//... Use array normally

//Deallocation
for (int i = 0; i < NumElements; ++i)
(ArrayOfClasses + i)->~cClass();
delete [] (char*)ArrayOfClasses;




Placement new doesn't actually allocate memory, it merely constructs a new object in memory that is already allocated. So you allocate a byte array that's large enough for all your objects, call the appropriate constructor on each element using placement new; then when you're done, you manually call the destructor of each element, and then delete the byte array to free the memory.

Share this post


Link to post
Share on other sites
No explicit per-element initialization can be done when allocating arrays using the new operator; only the default constructor, if present, is called.

Sorry.

frob.

Share this post


Link to post
Share on other sites
Quote:
Original post by Agony
[edit]Boo for beating me. By the way, does std::vector require a default constructor? I suppose it just internally allocates bytes and uses placement new as well, though, so probably not. If that's the case, then yeah, I agree, use std::vector. I would've mentioned it before placement new, but I was thinking that it required the existence of a default constructor.[/edit]


std::vector imposes no requirements on the type contained, remember that STL containers are parameterized by allocator type. The allocator *concept* separates allocation/deallocation and construction/destruction, in-fact when the default allocator is used std::allocator std::vector bascially becomes my method 2 all wrapped with some exception safety guarantees and guaranteed contiguousness of elements.


Quote:
Original post by frob
No explicit per-element initialization can be done when allocating arrays using the new operator; only the default constructor, if present, is called.


You must have missed the previous replies [grin]

Share this post


Link to post
Share on other sites
Quote:
Original post by Aiursrage2k
Hang on a tick, why would you want to explicity call the destructor, it seems redundant since delete[] does it anyway.


If your referring to placement new operator your wrong it wont, if you use placement new operator you must invoke the destructor explicitly for user-defined types, i think you should take another look at my method number 2 above.

Share this post


Link to post
Share on other sites
Quote:
Original post by Aiursrage2k
Hang on a tick, why would you want to explicity call the destructor, it seems redundant since delete[] does it anyway.


Only if you've allocated with new[]. If you use a placement new, you must call the destructor manually. snk_kid used the operators new and delete instead of the keywords. Thus only memory allocation is done, no constructor/destructor calls. If you really wanted to use new[] and delete[], you would do so via an array of char.

Share this post


Link to post
Share on other sites
I'm not sure if contents of a std::vector need to model default-constructible, but they definitely do need to model copy-constructible.

And there *are* at least two arguable disadvantages to using a std::vector for an array of statically known size:

1) storing said size at runtime (i.e. the overhead of the std::vector object itself).
2) lack of a guarantee on the size (the programmer is responsible, if that statically known size is important for the correctness of certain algorithms, for making sure that things like erase() or push_back() don't get called on the vector as a result of passing it to someone else's API).

But those are both trivial compared to the problems with the other approaches :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!