A dynamic Array of Classes with Constructors [SOLVED]

Started by
8 comments, last by Zahlman 18 years, 12 months ago
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]
Advertisement
You could just make a create method.
foo *bar = new foo[4];
for(int i=0; i<4; i++)
bar.create(Device);
Insufficent Information: we need more infromationhttp://staff.samods.org/aiursrage2k/
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]
[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;//AllocationArrayOfClasses = (cClass*)(new char[sizeof(cClass) * NumElements]);for (int i = 0; i < NumElements; ++i)  new (ArrayOfClasses + i) cClass(g_Device);//... Use array normally//Deallocationfor (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.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke
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.
Hang on a tick, why would you want to explicity call the destructor, it seems redundant since delete[] does it anyway.
Insufficent Information: we need more infromationhttp://staff.samods.org/aiursrage2k/
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]
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.
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.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
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 :)

This topic is closed to new replies.

Advertisement