If you use malloc()
with non-POD classes, you must call constructors (via placement new
) and destructors manually.
Using an object which was not constructed properly results in undefined behavior, which often means a crash when it comes to pointers.
Obviously, freeing a memory for object without a proper destruction of it causes UB too.
Your code must look like this:
MyClass *arr = (MyClass *) malloc(10 * sizeof (MyClass));
for (int i = 0; i < 10; i++)
new (arr + i) MyClass; // This line calls constructors
// Do something with the array here
for (int i = 0; i < 10; i++)
arr[i].~MyClass(); // This line calls destructors.
free(arr);
This requirement also means that you can't use realloc()
with non-POD types, because it wont call destructors for the old array and contructors for the new one for you.
Manual reallocation code might look like this:
MyClass *new_ptr = (MyClass *) malloc(new_size * sizeof (MyClass));
for (int i = 0; i < new_size; i++)
new (new_ptr + i) MyClass((MyClass &&) old_ptr[i]);
for (int i = new_size; i < old_size; i++)
new (new_ptr + i) MyClass;
for (int i = 0; i < old_size; i++)
old_ptr[i].~MyClass();
free(old_ptr);
And please keep in mind that above code is not really exception-safe. If a constructor throws an exception and you catch it, then you want to be sure that you properly destruct objects which were constructed. Thanks @SteveJessop.
Now when you understand why malloc()
/free()
usually should be avoided in C++, I hope you'll return to a lot more safe new
/delete
, which do all that construction and destruction for you.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…