Home > Software engineering >  How can i call the parameterized constructor for all objects in my dynamic array of objects on alloc
How can i call the parameterized constructor for all objects in my dynamic array of objects on alloc

Time:05-03

When i define dynamic array of objects, i want to choose one parameterized constructor for all objects in my array. without having to write for each object the chosen constructor like this

#include <iostream>

using namespace std;


class foo {
public:
    foo ()
    { 
        cout << "default constructor" << endl;
    }


    foo (int x)
    {
        cout << "parameterized constructor " << endl;
    }

    ~foo ()
    {
        cout << "destructor" << endl;
    }
};


int main (void)
{
    int size = 3, parameter = 10;
    foo *array;
    array = new foo [size] { foo(parameter), foo(parameter), foo(parameter) };

    cout << endl;

    delete [] array;
    return 0;
}

output

parameterized constructor 
parameterized constructor 
parameterized constructor 

destructor
destructor
destructor

So, as you can see from the above code, I can choose parameterized constructor for each object in my array array = new foo [size] { foo(parameter), foo(parameter), foo(parameter) };. However, if user inputs the size. same trick won't work

When I searched for solution, I found that I can do it with copy constructor like this

#include <iostream>

using namespace std;


class foo {
public:
    foo ()
    { 
        cout << "default constructor" << endl;
    }


    foo (int x)
    {
        cout << "parameterized constructor " << endl;
    }

    ~foo ()
    {
        cout << "destructor" << endl;
    }
};


int main (void)
{
    int size = 3, parameter = 10;
    foo *array;
    array = new foo [size];

    cout << endl;

    for (int i = 0; i < size; i  )
        array[i] = foo(parameter);

    cout << endl;
    
    delete [] array;
    return 0;
}

output

default constructor
default constructor
default constructor

parameterized constructor 
destructor
parameterized constructor 
destructor
parameterized constructor 
destructor

destructor
destructor
destructor

However, destructors are called for each object, and i don't want this i just want to do it while allocating for the first time

Thanks in advance, and I hope that there's a solution.

CodePudding user response:

The simplest solution to this problem would be to use std::vector which handles all those problems internally, e.g.:

#include <vector>
// skipping class declaration for brevity
int main (void)
{
    int size = 3, parameter = 10;
    std::vector<foo> array;
    array.reserve(size);

    cout << endl;

    for (int i = 0; i < size; i  )
        array.emplace_back(parameter);

    cout << endl;

    return 0;
}

However, if for some reason you want/need to do this by hand then you should be allocating a "raw buffer" and construct objects inside that buffer with placement new - this will however also require you to manually call the destructors

One possible example, doing everything "manually" could look like this

int main (void)
{
    int size = 3, parameter = 10;
    foo *array = reinterpret_cast<foo*>(new char[size * sizeof(foo)]);

    cout << endl;

    for (int i = 0; i < size; i  )
        new (&array[i]) foo(parameter);

    cout << endl;

    for (int i = 0; i < size; i  )
        array[i].~foo();

    delete[] reinterpret_cast<char*>(array);
    return 0;
}

An arguably cleaner solution is to use std::allocator and std::allocator_traits - this would look like this

#include <memory>
// skipping class declaration
int main (void)
{
    std::allocator<foo> alloc;
    using alloc_t = std::allocator_traits<decltype(alloc)>;
    int size = 3, parameter = 10;
    foo *array;
    array = alloc_t::allocate(alloc, size);

    cout << endl;

    for (int i = 0; i < size; i  )
        alloc_t::construct(alloc, &array[i], parameter);

    cout << endl;

    for (int i = 0; i < size; i  )
        alloc_t::destroy(alloc, &array[i]);
    
    alloc_t::deallocate(alloc, array, size);
    return 0;
}

CodePudding user response:

I would use a for loop :

array = new foo [size];
for(int i = 0; i < size; i  ) {
   array[i] = foo(parameter);
}

I don't see a simpler way to do it. And with this method, your size can be parametrized easily.

For your "destructor issue", use pointer on foo :

array = new *foo[size];
for(int i = 0; i < size; i  ) {
   array[i] = new foo(parameter);
}

But do not forget to delete each foo instance when needed :

for(int i = 0; i < size i  ) {
   delete array[i];
}
delete[] array;
  • Related