2

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

3
  • 1
    Congratulations, you have reinvented std::vector. Commented Oct 21, 2014 at 23:04
  • This is basically what std::vector does -- but you should only do this if you know what you are doing, and you should definitely implement these dangerous parts inside of a class so you only have to get it right one time. Or... just use std::vector since they already did that for you. For example, your delete[] is going to destruct even the uninitialized objects, which is harmless in this case but may be disastrous if you have a non-POD class. You would need to explicitly call the destructor of only the objects you placement-new'd, and then use ::operator delete on the array. Commented Oct 21, 2014 at 23:04
  • delete[] b; invokes Undefined Behaviour. The pointer must be from an array-new-expression. I.e. you'll have to call the destructors manually and call ::operator delete. Commented Oct 21, 2014 at 23:10

2 Answers 2

3

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) };
Sign up to request clarification or add additional context in comments.

1 Comment

This is new in C++11, which explains why many sources say it's impossible. Note however that the first one doesn't work with a run-time array size.
2

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])));.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.