Reputation: 21
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
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
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