When would anyone use a union? Is it a remnant from the C-only days? When would anyone use a union? Is it a remnant from the C-only days? c c

When would anyone use a union? Is it a remnant from the C-only days?


Unions are usually used with the company of a discriminator: a variable indicating which of the fields of the union is valid. For example, let's say you want to create your own Variant type:

struct my_variant_t {    int type;    union {        char char_value;        short short_value;        int int_value;        long long_value;        float float_value;        double double_value;        void* ptr_value;    };};

Then you would use it such as:

/* construct a new float variant instance */void init_float(struct my_variant_t* v, float initial_value) {    v->type = VAR_FLOAT;    v->float_value = initial_value;}/* Increments the value of the variant by the given int */void inc_variant_by_int(struct my_variant_t* v, int n) {    switch (v->type) {    case VAR_FLOAT:        v->float_value += n;        break;    case VAR_INT:        v->int_value += n;        break;    ...    }}

This is actually a pretty common idiom, specially on Visual Basic internals.

For a real example see SDL's SDL_Event union. (actual source code here). There is a type field at the top of the union, and the same field is repeated on every SDL_*Event struct. Then, to handle the correct event you need to check the value of the type field.

The benefits are simple: there is one single data type to handle all event types without using unnecessary memory.


I find C++ unions pretty cool. It seems that people usually only think of the use case where one wants to change the value of a union instance "in place" (which, it seems, serves only to save memory or perform doubtful conversions).

In fact, unions can be of great power as a software engineering tool, even when you never change the value of any union instance.

Use case 1: the chameleon

With unions, you can regroup a number of arbitrary classes under one denomination, which isn't without similarities with the case of a base class and its derived classes. What changes, however, is what you can and can't do with a given union instance:

struct Batman;struct BaseballBat;union Bat{    Batman brucewayne;    BaseballBat club;};ReturnType1 f(void){    BaseballBat bb = {/* */};    Bat b;    b.club = bb;    // do something with b.club}ReturnType2 g(Bat& b){    // do something with b, but how do we know what's inside?}Bat returnsBat(void);ReturnType3 h(void){    Bat b = returnsBat();    // do something with b, but how do we know what's inside?}

It appears that the programmer has to be certain of the type of the content of a given union instance when he wants to use it. It is the case in function f above. However, if a function were to receive a union instance as a passed argument, as is the case with g above, then it wouldn't know what to do with it. The same applies to functions returning a union instance, see h: how does the caller know what's inside?

If a union instance never gets passed as an argument or as a return value, then it's bound to have a very monotonous life, with spikes of excitement when the programmer chooses to change its content:

Batman bm = {/* */};Baseball bb = {/* */};Bat b;b.brucewayne = bm;// stuffb.club = bb;

And that's the most (un)popular use case of unions. Another use case is when a union instance comes along with something that tells you its type.

Use case 2: "Nice to meet you, I'm object, from Class"

Suppose a programmer elected to always pair up a union instance with a type descriptor (I'll leave it to the reader's discretion to imagine an implementation for one such object). This defeats the purpose of the union itself if what the programmer wants is to save memory and that the size of the type descriptor is not negligible with respect to that of the union. But let's suppose that it's crucial that the union instance could be passed as an argument or as a return value with the callee or caller not knowing what's inside.

Then the programmer has to write a switch control flow statement to tell Bruce Wayne apart from a wooden stick, or something equivalent. It's not too bad when there are only two types of contents in the union but obviously, the union doesn't scale anymore.

Use case 3:

As the authors of a recommendation for the ISO C++ Standard put it back in 2008,

Many important problem domains require either large numbers of objects or limited memory resources. In these situations conserving space is very important, and a union is often a perfect way to do that. In fact, a common use case is the situation where a union never changes its active member during its lifetime. It can be constructed, copied, and destructed as if it were a struct containing only one member. A typical application of this would be to create a heterogeneous collection of unrelated types which are not dynamically allocated (perhaps they are in-place constructed in a map, or members of an array).

And now, an example, with a UML class diagram:

many compositions for class A

The situation in plain English: an object of class A can have objects of any class among B1, ..., Bn, and at most one of each type, with n being a pretty big number, say at least 10.

We don't want to add fields (data members) to A like so:

private:    B1 b1;    .    .    .    Bn bn;

because n might vary (we might want to add Bx classes to the mix), and because this would cause a mess with constructors and because A objects would take up a lot of space.

We could use a wacky container of void* pointers to Bx objects with casts to retrieve them, but that's fugly and so C-style... but more importantly that would leave us with the lifetimes of many dynamically allocated objects to manage.

Instead, what can be done is this:

union Bee{    B1 b1;    .    .    .    Bn bn;};enum BeesTypes { TYPE_B1, ..., TYPE_BN };class A{private:    std::unordered_map<int, Bee> data; // C++11, otherwise use std::mappublic:    Bee get(int); // the implementation is obvious: get from the unordered map};

Then, to get the content of a union instance from data, you use a.get(TYPE_B2).b2 and the likes, where a is a class A instance.

This is all the more powerful since unions are unrestricted in C++11. See the document linked to above or this article for details.


One example is in the embedded realm, where each bit of a register may mean something different. For example, a union of an 8-bit integer and a structure with 8 separate 1-bit bitfields allows you to either change one bit or the entire byte.