No, this won't work
Sorry to be direct, but the use of void*
as you did is a very bad practice. This C like shortcut will not work correctly in C++, at least not when you use array of anything else that fundamental types !
Because casting a pointer to an object to a void
pointer, doesn't allow the compiler to generate the code required for the C++ object lifecycle.
So let's use a helper class to demonstrate what's wrong:
class C1 {
public:
C1() { cout<<" C1 object constructed"<<endl; }
~C1() { cout<<" C1 object destroyed"<<endl; }
};
Here an online demo of the problem that I'll explain step by step hereafter.
Case 1: manual allocation with a pointer
Every C1 allocated in the array, will be created and destroyed, with the following simple code:
C1 *p = new C1[2]; // every new []
delete[] p; // requires delete[]
Case 2: manual allocation pushed into a vector of pointers:
When a vector gets destroyed or gets cleared, so does its content. However, with a vetor of pointers, the pointer gets destroyed and not the object that is pointed to:
So this will not work; it will leak memory:
vector<C1*> v;
v.push_back(new C1[2]); // C1 objects are created
v.clear(); // pointers are lost but C1 objects are not derleted.
If you insert the following statement before the clear
, everything is ok again: all C1 that are created are destroyed:
for (auto &x:v)
delete[]x;
v.clear();
Case 3: the void* alternative is doomed to fail:
If we take the working code above but use a casting to void*
, the C1 objects are created, but they are not destroyed:
std::vector<void*> data;
data.push_back(new C1[2]); // yes, creating works and ponter is in ector
for (auto &x:data)
delete[]x; // ouch, deletes a void* so it doesn't know that it's a C1 object
data.clear();
How to solve it ?
Well, you need a common denominator for the objects that you store on your vector, for example:
- use inheritance and a common base type for all the elements.
- use a union with a type selector to be able to know the type of the objects that are pointed to
- use
boost::variant
objects
If you have a common base type you could consider the vector of vector alternative to get rid of the manual memory management.