I'm writing code and until now I was using structures like this:
struct s{
enum Types { zero = 0, one, two };
unsigned int type;
void* data;
}
I needed some generic structure to store data from different classes and I wanted to use it in std::vector, so that's reason why I can't use templates. What's better option: unions or void pointers?
Void pointer allocates only as much space as I need, but c++ is strong typed language for some reason and casting everywhere I need to use those data is not the way c++ code should be designed. As I read, void pointers shouldn't be used unless there's no alternative.
That alternative could be Unions. They comes with c++ and uses the same memory space for every member, very much like void pointers. However they come at price - allocated space is the size of largest element in union, and in my case differences between sizes are big.
This is rather stylistic and "correct language using" problem, as both ways accomplish what I need to do, but I can't decide if nicely stylized c++ code can pay for that wasted memory (even though memory these days isn't a big concern).
Consider boost::any
or boost::variant
if you want to store objects of heterogeneous types.
And before deciding which one to use, have a look at the comparison:
Hopefully, it will help you to make the correct decision. Choose one, and any of the container from the standard library to store the objects, std::vector<boost::any>
, std::vector<boost::variant>
, or any other.
Basically, it is a type-safe union, and in this case, it seems like unions are by far the most appropriate answer. A void*
could be used, but that would mean dynamic allocation, and you would have to maintain the Types
enum
, and the table for casting.
Memory constraints could make void*
an acceptable choice, but it's not the 'neat' answer, and I wouldn't go for it until both boost::variant
and just a plain union
have shown to be unacceptable.
If your classes have enough in common to be put in the same container give them a base class with a virtual destructor, and possibly a virtual member function to retrieve your type code, even though at that point not only dynamic_cast would be more appropriate, but it could be reasonable to explore whether your classes don't have enough in common to provide them with a more complete common interface.
Otherwise consider providing a custom container class with appropriately typed data members to hold instances of all the different classes you need to put into it.
来源:https://stackoverflow.com/questions/7132248/union-vs-static-castvoid