osgx
osgx

Reputation: 94445

C++, array of objects without <vector>

I want to create in C++ an array of Objects without using STL.

How can I do this?

How could I create array of Object2, which has no argumentless constructor (default constructor)?

Upvotes: 32

Views: 70042

Answers (9)

Kirill V. Lyadvinsky
Kirill V. Lyadvinsky

Reputation: 99675

// allocate memory
Object2* objArray = static_cast<Object2*>( ::operator new ( sizeof Object2 * NUM_OF_OBJS ) );
// invoke constuctors
for ( size_t i = 0; i < NUM_OF_OBJS; i++ )
  new (&objArray[i]) Object2( /* initializers */ );

// ... do some work

// invoke destructors
for ( size_t i = 0; i < NUM_OF_OBJS; i++ )
  objArray[i].~Object2();

// deallocate memory
::operator delete ( objArray );

Upvotes: 13

anon
anon

Reputation:

You can do what std::vector does and create a block of raw memory. You then construct your objects which don't have a default constructor in that memory using placement new, as they are required. But of course, if you do that you might as well have used std::vector in the first place.

Upvotes: 3

CB Bailey
CB Bailey

Reputation: 792847

If you genuinely need an array (contiguous sequence of objects) of a non-default constructible type and for some reason you cannoy user std::vector (!?) then you have to use a raw allocation function and placement new.

This is very hard to do reliably; this should help to show why. This snippet includes some defence against exceptions but is more than likely not robust against all failures.

const size_t required_count = 100; //e.g.

// cast to pointer of required type needed for pointer arithmetic
Object2* objarray = static_cast<Object2*>(operator new(required_count * sizeof(Object2)));

size_t construction_count = 0;

try
{
    while (construction_count < required_count)
    {
        // params could change with index.
        new (static_cast<void*>(objarray + construction_count)) Object2(param1, param2);
        ++construction_count;
    }
}
catch (...)
{
    while (construction_count-- != 0)
    {
        try
        {
            (&objarray[construction_count])->~Object2();
        }
        catch (...)
        {
            // not a lot we can do here, log but don't re-throw.
        }
    }

    operator delete(objarray);
    throw;
}

// Now objarray has been allocated and pointer to an array of required_count Object2
// It cannot be de-allocated via delete[] or delete; you must loop through
// calling destructors and then call operator delete on the buffer.

Upvotes: 0

Jeremy Bell
Jeremy Bell

Reputation: 5293

Use an array of pointers to Object2:

std::tr1::shared_ptr<Object2>* newArray = new shared_ptr<Object2>[numberOfObjects];
for(int i = 0; i < numberOfObjects; i++)
{
    newArray[i] = shared_ptr<Object2>(new Object2(params));
}

Or, alternatively, without the use of shared_ptr:

Object2** newArray = new Object2*[numberOfObjects];
for(int i = 0; i < numberOfObjects; i++)
{
    newArray[i] = new Object2(params);
}

Upvotes: 3

mukeshkumar
mukeshkumar

Reputation: 2778

Assuming that your class is Base and you have a one argument constructor

Base arr[3] = {Base(0), Base(1), Base(2)} ;

Upvotes: 13

sharptooth
sharptooth

Reputation: 170539

If the type in question has an no arguments constructor, use new[]:

Object2* newArray = new Object2[numberOfObjects];

don't forget to call delete[] when you no longer need the array:

delete[] newArray;

If it doesn't have such a constructor use operator new to allocate memory, then call constructors in-place:

//do for each object
::new( addressOfObject ) Object2( parameters );

Again, don't forget to deallocate the array when you no longer need it.

Upvotes: 35

David Thornley
David Thornley

Reputation: 57066

The obvious question is why you don't want to use the STL.

Assuming you have a reason, you would create an array of objects with something like Obj * op = new Obj[4];. Just remember to get rid of it with delete [] op;.

You can't do that with an object with no constructor that doesn't take arguments. In that case, I think the best you could do is allocate some memory and use placement new. It isn't as straightforward as the other methods.

Upvotes: 0

Raul Agrait
Raul Agrait

Reputation: 6018

Object2 *myArray[42];
for (int i = 0; i < 42; i++)
{
  myArray[i] = new Object2(param1, param2, ...);
}

Later on you will have to walk through the array and deallocate each member individually:

for (int j = 0; j < 42; j++)
{
  delete myArray[j];
}

Upvotes: 5

Bj&#246;rn Pollex
Bj&#246;rn Pollex

Reputation: 76866

If no default constructor is available, you will need an array of pointers, and then loop over that array to initialize each of the pointers.

Upvotes: 0

Related Questions