Public Group

# A dynamic Array of Classes with Constructors [SOLVED]

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

## 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 on other sites
You could just make a create method.
foo *bar = new foo[4];
for(int i=0; i<4; i++)
bar.create(Device);

##### Share on other sites
Quote:
 Original post by kag1What 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(/*...*/));

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

##### Share on other sites
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.

##### 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 on other sites
Hang on a tick, why would you want to explicity call the destructor, it seems redundant since delete[] does it anyway.

##### Share on other sites
Quote:
 Original post by AgonyBoo 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 frobNo 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 on other sites
Quote:
 Original post by Aiursrage2kHang 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 on other sites
Quote:
 Original post by Aiursrage2kHang 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 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 :)

• 22
• 10
• 19
• 15
• 14