Skip to content

Commit 195f02a

Browse files
authored
Merge pull request MicrosoftDocs#3061 from corob-msft/docs/corob/2390
Fix for cpp-docs issue 2390 stray char in sample
2 parents eea02f7 + 17fefb6 commit 195f02a

File tree

1 file changed

+53
-143
lines changed

1 file changed

+53
-143
lines changed

docs/cpp/unions.md

Lines changed: 53 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,36 @@
11
---
2-
title: "Unions"
3-
ms.date: "05/06/2019"
2+
title: "union"
3+
description: "A description of the Standard C++ union class-type and keyword, its use and restrictions."
4+
ms.date: "08/18/2020"
45
f1_keywords: ["union_cpp"]
5-
helpviewer_keywords: ["class types [C++], unions as", "union keyword [C++]"]
6+
helpviewer_keywords: ["class type [C++], union as", "union keyword [C++]"]
67
ms.assetid: 25c4e219-fcbb-4b7b-9b64-83f3252a92ca
8+
no-loc: ["union", "struct", "enum", "class", "static"]
79
---
8-
# Unions
10+
# `union`
911

1012
> [!NOTE]
11-
> In C++17 and later, the **std::variant** class is a type-safe alternative for unions.
13+
> In C++17 and later, the `std::variant` class is a type-safe alternative for a union.
1214
13-
A **`union`** is a user-defined type in which all members share the same memory location. This means that at any given time a union can contain no more than one object from its list of members. It also means that no matter how many members a union has, it always uses only enough memory to store the largest member.
15+
A **`union`** is a user-defined type in which all members share the same memory location. This definition means that at any given time, a union can contain no more than one object from its list of members. It also means that no matter how many members a union has, it always uses only enough memory to store the largest member.
1416

15-
Unions can be useful for conserving memory when you have lots of objects and/or limited memory. However they require extra care to use correctly because you are responsible for ensuring that you always access the last member that was written to. If any member types have a non-trivial constructor, then you must write additional code to explicitly construct and destroy that member. Before using a union, consider whether the problem you are trying to solve could be better expressed by using a base class and derived classes.
17+
A union can be useful for conserving memory when you have lots of objects and limited memory. However, a union requires extra care to use correctly. You're responsible for ensuring that you always access the same member you assigned. If any member types have a non-trivial constructor, then you must write additional code to explicitly construct and destroy that member. Before you use a union, consider whether the problem you're trying to solve could be better expressed by using a base class and derived class types.
1618

1719
## Syntax
1820

19-
```cpp
20-
union [name] { member-list };
21-
```
21+
> **`union`** *`tag`*<sub>opt</sub> **`{`** *`member-list`* **`};`**
2222
2323
### Parameters
2424

25-
*name*<br/>
25+
*`tag`*<br/>
2626
The type name given to the union.
2727

28-
*member-list*<br/>
29-
Members that the union can contain. See Remarks.
30-
31-
## Remarks
28+
*`member-list`*<br/>
29+
Members that the union can contain.
3230

33-
## Declaring a Union
31+
## Declare a union
3432

35-
Begin the declaration of a union with the **`union`** keyword, and enclose the member list in curly braces:
33+
Begin the declaration of a union by using the **`union`** keyword, and enclose the member list in curly braces:
3634

3735
```cpp
3836
// declaring_a_union.cpp
@@ -45,6 +43,7 @@ union RecordType // Declare a simple union type
4543
double d;
4644
int *int_ptr;
4745
};
46+
4847
int main()
4948
{
5049
RecordType t;
@@ -53,9 +52,9 @@ int main()
5352
}
5453
```
5554

56-
## Using unions
55+
## Use a union
5756

58-
In the previous example, any code that accesses the union needs to know which member is holding the data. The most common solution to this problem is to enclose the union in a struct along with an additional enum member that indicates the type of the data currently being stored in the union. This is called a *discriminated union* and the following example shows the basic pattern.
57+
In the previous example, any code that accesses the union needs to know which member holds the data. The most common solution to this problem is called a *discriminated union*. It encloses the union in a struct, and includes an enum member that indicates the member type currently stored in the union. The following example shows the basic pattern:
5958

6059
```cpp
6160
#include <queue>
@@ -98,16 +97,27 @@ struct Input
9897
void Process_Temp(TempData t) {}
9998
void Process_Wind(WindData w) {}
10099

101-
// Container for all the data records
102-
queue<Input> inputs;
103-
void Initialize();
100+
void Initialize(std::queue<Input>& inputs)
101+
{
102+
Input first;
103+
first.type = WeatherDataType::Temperature;
104+
first.temp = { 101, 1418855664, 91.8, 108.5, 67.2 };
105+
inputs.push(first);
106+
107+
Input second;
108+
second.type = WeatherDataType::Wind;
109+
second.wind = { 204, 1418859354, 14, 27 };
110+
inputs.push(second);
111+
}
104112

105113
int main(int argc, char* argv[])
106114
{
107-
Initialize();
115+
// Container for all the data records
116+
queue<Input> inputs;
117+
Initialize(inputs);
108118
while (!inputs.empty())
109119
{
110-
Input i = inputs.front();
120+
Input const i = inputs.front();
111121
switch (i.type)
112122
{
113123
case WeatherDataType::Temperature:
@@ -124,29 +134,17 @@ int main(int argc, char* argv[])
124134
}
125135
return 0;
126136
}
127-
128-
void Initialize()
129-
{
130-
Input first, second;
131-
first.type = WeatherDataType::Temperature;
132-
first.temp = { 101, 1418855664, 91.8, 108.5, 67.2 };
133-
inputs.push(first);
134-
135-
second.type = WeatherDataType::Wind;
136-
second.wind = { 204,1418859354, 14, 27 };
137-
inputs.push(second);
138-
}
139137
```
140138
141-
In the previous example, note that the union in the Input struct has no name. This is an anonymous union and its members can be accessed as if they were direct members of the struct. For more information about anonymous unions, see the section below.
139+
In the previous example, the union in the `Input` struct has no name, so it's called an *anonymous* union. Its members can be accessed directly as if they're members of the struct. For more information about how to use an anonymous union, see the [Anonymous union](#anonymous_unions) section.
142140
143-
Of course, the previous example shows a problem that could also be solved by using classes that derive from a common base class, and branching your code based on the runtime type of each object in the container. This may result in code that easier to maintain and understand, but it might also be slower than using unions. Also, with a union, you can store completely unrelated types, and dynamically change the type of the value that is stored without changing the type of the union variable itself. Thus you can create a heterogeneous array of MyUnionType whose elements store different values of different types.
141+
The previous example shows a problem that you could also solve by using class types that derive from a common base class. You could branch your code based on the runtime type of each object in the container. Your code might be easier to maintain and understand, but it might also be slower than using a union. Also, with a union, you can store unrelated types. A union lets you dynamically change the type of the stored value without changing the type of the union variable itself. For example, you could create a heterogeneous array of `MyUnionType`, whose elements store different values of different types.
144142
145-
Note that the `Input` struct in the preceding example can be easily misused. It is completely up to the user to use the discriminator correctly to access the member that holds the data. You can protect against misuse by making the union private and providing special access functions, as shown in the next example.
143+
It's easy to misuse the `Input` struct in the example. It's up to the user to use the discriminator correctly to access the member that holds the data. You can protect against misuse by making the union **`private`** and providing special access functions, as shown in the next example.
146144
147-
## Unrestricted Unions (C++11)
145+
## Unrestricted union (C++11)
148146
149-
In C++03 and earlier a union can contain non-static data members with class type as long as the type has no user provided constructors, destructors or assignment operators. In C++11, these restrictions are removed. If you include such a member in your union then the compiler will automatically mark any special member functions that are not user provided as deleted. If the union is an anonymous union inside a class or struct, then any special member functions of the class or struct that are not user provided are marked as deleted. The following example shows how to handle the case where one of the members of the union has a member that requires this special treatment:
147+
In C++03 and earlier, a union can contain non-static data members that have a class type, as long as the type has no user provided constructors, destructors, or assignment operators. In C++11, these restrictions are removed. If you include such a member in your union, the compiler automatically marks any special member functions that aren't user provided as **`deleted`**. If the union is an anonymous union inside a class or struct, then any special member functions of the class or struct that aren't user provided are marked as **`deleted`**. The following example shows how to handle this case. One of the members of the union has a member that requires this special treatment:
150148
151149
```cpp
152150
// for MyVariant
@@ -504,97 +502,11 @@ int main()
504502
char c;
505503
cin >> c;
506504
}
507-
#include <queue>
508-
#include <iostream>
509-
using namespace std;
510-
511-
enum class WeatherDataType
512-
{
513-
Temperature, Wind
514-
};
515-
516-
struct TempData
517-
{
518-
TempData() : StationId(""), time(0), current(0), maxTemp(0), minTemp(0) {}
519-
TempData(string id, time_t t, double cur, double max, double min)
520-
: StationId(id), time(t), current(cur), maxTemp(max), minTemp(0) {}
521-
string StationId;
522-
time_t time = 0;
523-
double current;
524-
double maxTemp;
525-
double minTemp;
526-
};
527-
528-
struct WindData
529-
{
530-
int StationId;
531-
time_t time;
532-
int speed;
533-
short direction;
534-
};
535-
536-
struct Input
537-
{
538-
Input() {}
539-
Input(const Input&) {}
540-
541-
~Input()
542-
{
543-
if (type == WeatherDataType::Temperature)
544-
{
545-
temp.StationId.~string();
546-
}
547-
}
548-
549-
WeatherDataType type;
550-
void SetTemp(const TempData& td)
551-
{
552-
type = WeatherDataType::Temperature;
553-
554-
// must use placement new because of string member!
555-
new(&temp) TempData(td);
556-
}
557-
558-
TempData GetTemp()
559-
{
560-
if (type == WeatherDataType::Temperature)
561-
return temp;
562-
else
563-
throw logic_error("Can't return TempData when Input holds a WindData");
564-
}
565-
void SetWind(WindData wd)
566-
{
567-
// Explicitly delete struct member that has a
568-
// non-trivial constructor
569-
if (type == WeatherDataType::Temperature)
570-
{
571-
temp.StationId.~string();
572-
}
573-
wind = wd; //placement new not required.
574-
}
575-
WindData GetWind()
576-
{
577-
if (type == WeatherDataType::Wind)
578-
{
579-
return wind;
580-
}
581-
else
582-
throw logic_error("Can't return WindData when Input holds a TempData");
583-
}
584-
585-
private:
586-
587-
union
588-
{
589-
TempData temp;
590-
WindData wind;
591-
};
592-
};
593505
```
594506

595-
Unions cannot store references. Unions don’t support inheritance, therefore a union itself cannot be used as a base class, or inherit from another class, or have virtual functions.
507+
A union can't store a reference. A union also doesn’t support inheritance. That means you can't use a union as a base class, or inherit from another class, or have virtual functions.
596508

597-
## Initializing unions
509+
## Initialize a union
598510

599511
You can declare and initialize a union in the same statement by assigning an expression enclosed in braces. The expression is evaluated and assigned to the first field of the union.
600512

@@ -614,7 +526,7 @@ int main()
614526
union NumericType Values = { 10 }; // iValue = 10
615527
cout << Values.iValue << endl;
616528
Values.dValue = 3.1416;
617-
cout << Values.dValue) << endl;
529+
cout << Values.dValue << endl;
618530
}
619531
/* Output:
620532
10
@@ -625,29 +537,27 @@ int main()
625537
The `NumericType` union is arranged in memory (conceptually) as shown in the following figure.
626538

627539
![Storage of data in a numeric type union](../cpp/media/vc38ul1.png "Storage of data in a NumericType union") <br/>
628-
Storage of Data in NumericType Union
540+
Storage of data in a `NumericType` union
629541

630-
## <a name="anonymous_unions"></a> Anonymous unions
542+
## <a name="anonymous_unions"></a> Anonymous union
631543

632-
Anonymous unions are unions that are declared without a *class-name* or *declarator-list*.
544+
An anonymous union is one declared without a *`class-name`* or *`declarator-list`*.
633545

634-
```cpp
635-
union { member-list }
636-
```
546+
> **`union {`** *`member-list`* **`}`**
637547
638-
Names declared in an anonymous union are used directly, like nonmember variables. Therefore, the names declared in an anonymous union must be unique in the surrounding scope.
548+
Names declared in an anonymous union are used directly, like nonmember variables. It implies that the names declared in an anonymous union must be unique in the surrounding scope.
639549

640-
In addition to the restrictions for named unions, anonymous unions are subject to these additional restrictions:
550+
An anonymous union is subject to these additional restrictions:
641551

642-
- They must also be declared as **`static`** if declared in file or namespace scope.
552+
- If declared in file or namespace scope, it must also be declared as **`static`**.
643553

644-
- They can have only **`public`** members; **`private`** and **`protected`** members in anonymous unions generate errors.
554+
- It can have only **`public`** members; having **`private`** and **`protected`** members in an anonymous union generates errors.
645555

646-
- They cannot have member functions.
556+
- It can't have member functions.
647557

648558
## See also
649559

650560
[Classes and Structs](../cpp/classes-and-structs-cpp.md)<br/>
651561
[Keywords](../cpp/keywords-cpp.md)<br/>
652-
[class](../cpp/class-cpp.md)<br/>
653-
[struct](../cpp/struct-cpp.md)
562+
[`class`](../cpp/class-cpp.md)<br/>
563+
[`struct`](../cpp/struct-cpp.md)

0 commit comments

Comments
 (0)