costas
costas

Reputation: 21

Creating an array of objects without a default constructor

I have read in many places that in c++ you cannot use the new[] operator to create an array of objects that do not have a default constructor. I also understand that I can use vectors to easily achieve this.

However, I tried the following code which did seem to give me the ability to use the new[] operator for an array of objects without a default constructor:

struct mystuff{
    int data1, data2;

    mystuff(int a){
        data1 = a;
        data2 = 10;
    }
    mystuff(int a, int g){
        data1 = a;
        data2 = g;
    }
};

int main(){
    mystuff *b = static_cast<mystuff*> (::operator new (sizeof(mystuff[5]))); //allocate memory
    for (int i = 0; i < 5; i++){
        std::cout << &b[i] << std::endl; //addresses of allocated memory
    }
    new (b + 1)mystuff(5); //initialize one of the values in the array with non default constructor
    new (b + 3)mystuff(10, 15); //initialize one of the values in the array with non default constructor
    std::cout << "\n" << std::endl;
    for (int i = 0; i < 5; i++){
        std::cout << &b[i] << std::endl; //addresses of allocated memory after constructor
    }

    std::cout << "Values of constructed objects" << std::endl;
    std::cout << b[1].data1 << "," << b[1].data2 << std::endl;
    std::cout << b[3].data1 << "," << b[3].data2 << std::endl;

    std::cin.get();

    delete[] b;
    return 0;
}

I would greatly appreciate it if someone can tell me whether this is a legitimate thing to do or if what is shown is very wrong and dangerous for some reason that I do not realize (i.e. I somehow created a memory leak in this specific example).

Thanks so much

Upvotes: 2

Views: 2855

Answers (2)

Anton Savin
Anton Savin

Reputation: 41301

What you are trying to do is essentially the same as std::vector is doing in its insides.

As it is, your code is not legitimate. First, for objects created with placement new you must call destructors manually:

b[1].~mystuff();
b[3].~mystuff();

And second, delete[] b is illegal because it's called for memory not allocated with new[], so you have undefined behavior. So you should replace it with ::operator delete(b); or ::operator delete(b, sizeof(mystuff[5])));.

Upvotes: 2

Kerrek SB
Kerrek SB

Reputation: 476990

You can provide initializers for dynamic arrays, and you can also populate vectors:

mystuff * b = new mystuff[3] { mystuff(1), mystuff(2, 3), mystuff(4) };
// *b is leaked

std::vector<mystuff> const c { mystuff(1), mystuff(2, 3), mystuff(4) };

Upvotes: 3

Related Questions