Posted Joe Chu cpp5 minutes read (About 714 words)0 visits
Union in C++
A union is a special class type that can hold only one of its non-static data members at a time.
1. Introduction
A union declaration is similar to struct/class declaration. Just like in struct declaration, the default member access in a union is public.
A union can have member functions (including constructors and destructors), but not virtual functions.
A union cannot have base classes and cannot be used as a base class.
A union cannot have non-static data members of reference types.
In a union, only one member can be activated at a time. We can only access the currently activated member. Accessing other inactivated members will have undefined behavior.
intmain(){ [[maybe_unused]] constexprauto a = union_size(); std::cout << "size of union: " << a << '\n'; // 8
/* Error: accessing 'union_activation()::U2::j' member instead of initialized 'union_activation()::U2::i' member in constant expression */ [[maybe_unused]] constexprauto b = union_activation(); }
2. Switch activated members
2.1 Trivial types
For trivial types, we can simply assign a new value to the member we want to activate.
intmain(){ U u; std::cout << u.x << '\n'; u = 2.; std::cout << u.y << '\n'; u = "hello, world"; std::cout << u.z << '\n'; }
2.2 Non-trivial types
For non-trivial types, we need to carefully manage the construction and destruction of the union members. This involves using placement new to construct a new member and explicitly calling the destructor of the previously active member.
// Initialize std::vector<int> new (&u.vec) std::vector<int>({1, 2, 3}); std::cout << "Vector content: "; for (int i : u.vec) { std::cout << i << " "; } std::cout << std::endl; u.vec.~vector<int>(); // Explicitly call the destructor
// Switch to std::string new (&u.str) std::string{"Hello, Union"}; std::cout << "String content: " << u.str << std::endl; u.str.~basic_string(); // Explicitly call the destructor
// Switch to CustomClass new (&u.a) A(3); u.a.print(); u.a.~A(); // Explicitly call the destructor
return0; }
1 2 3 4 5 6 7
U() Vector content: 1 2 3 String content: Hello, Union A(int x) called, x = 3 print x = 3 ~A() called ~U()
3. Anonymous unions
An anonymous union is a union without a name. Anonymous unions allow you to define a union directly within a class or a struct, and their members are accessed as if they are members of the enclosing class or struct. This feature can simplify the code by avoiding the need to explicitly refer to the union name when accessing its members.