312 lines
36 KiB
HTML
312 lines
36 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh" dir="ltr" class="client-nojs" xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh">
|
|
<head><meta http-equiv="x-ua-compatible" content="ie=edge">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
<title>联合体声明</title>
|
|
<link rel="stylesheet" href="ext.css" />
|
|
<link rel="stylesheet" href="site_modules.css" />
|
|
</head>
|
|
<body class="mediawiki ltr sitedir-ltr ns-0 ns-subject page-cpp_language_union skin-cppreference2 action-view cpp-navbar">
|
|
<div id="cpp-content-base">
|
|
<div id="content"><a id="top"></a>
|
|
<h1 id="firstHeading" class="firstHeading">联合体声明</h1>
|
|
<div id="bodyContent">
|
|
<div id="contentSub"><span class="subpages">< <a href="cpp.html">cpp</a>‎ | <a href="cpp-language.html">language</a></span></div>
|
|
<div id="mw-content-text" lang="zh" dir="ltr" class="mw-content-ltr" xml:lang="zh">
|
|
<p>联合体是特殊的类类型,它在一个时刻只能保有其一个非静态<a href="cpp-language-data_members.html">数据成员</a>。</p>
|
|
<p>联合体声明的类说明符与<a href="cpp-language-class.html">类或结构体</a>的声明相似:</p>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td class="t-sdsc-nopad"><code><b>union</b></code> <span class="t-spar">属性</span> <span class="t-spar">类头名</span> <code><b>{</b></code> <span class="t-spar">成员说明</span> <code><b>}</b></code></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<table class="t-par-begin">
|
|
<tr class="t-par">
|
|
<td><span class="t-spar">属性</span></td>
|
|
<td>-</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span> 任意数量<a href="cpp-language-attributes.html">属性</a>的可选序列</td>
|
|
</tr>
|
|
<tr class="t-par">
|
|
<td><span class="t-spar">类头名</span></td>
|
|
<td>-</td>
|
|
<td>被定义的联合体的名字。可以前附 <span class="t-spar">嵌套名说明符</span>(名字与作用域解析运算符的序列,以作用域解析运算符结尾)。可以忽略名字,此时联合体是<i>无名</i>的</td>
|
|
</tr>
|
|
<tr class="t-par">
|
|
<td><span class="t-spar">成员说明</span></td>
|
|
<td>-</td>
|
|
<td>访问说明符、成员对象和成员函数的声明与定义的列表。</td>
|
|
</tr>
|
|
</table>
|
|
<p>联合体可以拥有成员函数(包含构造函数和析构函数),但不能有虚函数。</p>
|
|
<p>联合体不能有基类且不能用作基类。</p>
|
|
<p>联合体不能拥有引用类型的非静态数据成员。</p>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-until-cxx11">
|
|
<td>
|
|
<p>联合体不能含有带非平凡特殊成员函数(<a href="cpp-language-copy_constructor.html">复制构造函数</a>、<a href="cpp-language-copy_assignment.html">复制赋值</a>运算符或<a href="cpp-language-destructor.html">析构函数</a>)的非静态数据成员。</p>
|
|
</td>
|
|
<td><span class="t-mark-rev t-until-cxx11">(C++11 前)</span></td>
|
|
</tr>
|
|
<tr class="t-rev t-since-cxx11">
|
|
<td>
|
|
<p>如果联合体含有带非平凡特殊成员函数(<a href="cpp-language-copy_constructor.html">复制</a>/<a href="cpp-language-move_constructor.html">移动</a>构造函数,<a href="cpp-language-copy_assignment.html">复制</a>/<a href="cpp-language-move_assignment.html">移动</a>赋值,或<a href="cpp-language-destructor.html">析构函数</a>)的非静态数据成员,那么该联合体中的那些函数默认被弃置,且需要程序员显式定义。</p>
|
|
<p>如果联合体含有带非平凡<a href="cpp-language-default_constructor.html">默认构造函数</a>的非静态数据成员,那么该联合体的默认构造函数默认被弃置,除非该联合体的<a href="cpp-language-union.html#.E8.81.94.E5.90.88.E4.BD.93.E5.BC.8F.E7.9A.84.E7.B1.BB">变体成员</a>拥有一个默认成员初始化器。</p>
|
|
<p>最多只有一个<a href="cpp-language-union.html#.E8.81.94.E5.90.88.E4.BD.93.E5.BC.8F.E7.9A.84.E7.B1.BB">变体成员</a>可以拥有<a href="cpp-language-data_members.html#.E6.88.90.E5.91.98.E5.88.9D.E5.A7.8B.E5.8C.96">默认成员初始化器</a>。</p>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<p>正如<a href="cpp-language-classes.html">结构体的</a>声明中一般,联合体的默认成员访问是 <a href="cpp-language-access.html">public</a>。</p>
|
|
<h3><span class="mw-headline" id=".E8.A7.A3.E9.87.8A">解释</span></h3>
|
|
<p>联合体的大小仅足以保有其最大的数据成员。其他数据成员在该最大成员的一部分相同的字节分配。分配的细节是实现定义的,且读取并非最近写入的联合体成员是未定义行为。许多编译器以非标准语言扩展实现读取联合体的不活跃成员的能力。</p>
|
|
<div class="t-example">
|
|
<div class="t-example-live-link"></div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co2">#include <iostream></span>
|
|
<span class="co2">#include <cstdint></span>
|
|
<span class="kw1">union</span> S
|
|
<span class="br0">{</span>
|
|
<a href="cpp-types-integer.html"><span class="kw108">std::<span class="me2">int32_t</span></span></a> n<span class="sy4">;</span> <span class="co1">// 占用 4 字节</span>
|
|
<a href="cpp-types-integer.html"><span class="kw121">std::<span class="me2">uint16_t</span></span></a> s<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span class="sy4">;</span> <span class="co1">// 占用 4 字节</span>
|
|
<a href="cpp-types-integer.html"><span class="kw120">std::<span class="me2">uint8_t</span></span></a> c<span class="sy4">;</span> <span class="co1">// 占用 1 字节</span>
|
|
<span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 整个联合体占用 4 字节</span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
S s <span class="sy1">=</span> <span class="br0">{</span><span class="nu12">0x12345678</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 初始化首个成员,s.n 现在是活跃成员</span>
|
|
<span class="co1">// 于此点,从 s.s 或 s.c 读取是未定义行为</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <a href="cpp-io-manip-hex.html"><span class="kw1782">std::<span class="me2">hex</span></span></a> <span class="sy1"><<</span> <span class="st0">"s.n = "</span> <span class="sy1"><<</span> s.<span class="me1">n</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
s.<span class="me1">s</span><span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span> <span class="sy1">=</span> <span class="nu12">0x0011</span><span class="sy4">;</span> <span class="co1">// s.s 现在是活跃成员</span>
|
|
<span class="co1">// 在此点,从 n 或 c 读取是 UB 但大多数编译器都对其有定义</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"s.c 现在是 "</span> <span class="sy1"><<</span> <span class="sy2">+</span>s.<span class="me1">c</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span> <span class="co1">// 11 或 00,取决于平台</span>
|
|
<span class="sy1"><<</span> <span class="st0">"s.n 现在是 "</span> <span class="sy1"><<</span> s.<span class="me1">n</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="co1">// 12340011 或 00115678</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<p>可能的输出:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="text source-text">
|
|
<pre class="de1">s.n = 12345678
|
|
s.c 现在是 0
|
|
s.n 现在是 115678</pre></div>
|
|
</div>
|
|
</div>
|
|
<p>每个成员的分配都如同它是类的唯一成员一样。</p>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx11">
|
|
<td>
|
|
<p>如果联合体的成员是拥有用户定义的构造函数和析构函数的类,那么切换其活跃成员通常需要显式析构函数和布置 new:</p>
|
|
<div class="t-example">
|
|
<div class="t-example-live-link"></div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co2">#include <iostream></span>
|
|
<span class="co2">#include <string></span>
|
|
<span class="co2">#include <vector></span>
|
|
|
|
<span class="kw1">union</span> S
|
|
<span class="br0">{</span>
|
|
<a href="cpp-string-basic_string.html"><span class="kw1230">std::<span class="me2">string</span></span></a> str<span class="sy4">;</span>
|
|
<a href="cpp-container-vector.html"><span class="kw1269">std::<span class="me2">vector</span></span></a><span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span> vec<span class="sy4">;</span>
|
|
~S<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span><span class="br0">}</span> <span class="co1">// 需要知道哪个成员活跃,只能在联合体式的类中做到</span>
|
|
<span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 整个联合体占有 max(sizeof(string), sizeof(vector<int>)) 的内存</span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
S s <span class="sy1">=</span> <span class="br0">{</span><span class="st0">"Hello, world"</span><span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="co1">// 在此点,从 s.vec 读取是未定义行为</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"s.str = "</span> <span class="sy1"><<</span> s.<span class="me1">str</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
s.<span class="me1">str</span>.~basic_string<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span>
|
|
new <span class="br0">(</span><span class="sy3">&</span>s.<span class="me1">vec</span><span class="br0">)</span> <a href="cpp-container-vector.html"><span class="kw1269">std::<span class="me2">vector</span></span></a><span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span><span class="sy4">;</span>
|
|
<span class="co1">// 现在,s.vec 是联合体的活跃成员</span>
|
|
s.<span class="me1">vec</span>.<span class="me1">push_back</span><span class="br0">(</span><span class="nu0">10</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> s.<span class="me1">vec</span>.<span class="me1">size</span><span class="br0">(</span><span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
s.<span class="me1">vec</span>.~vector<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<p>输出:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="text source-text">
|
|
<pre class="de1">s.str = Hello, world
|
|
1</pre></div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<p>如果两个联合体成员都是<a href="cpp-named_req-StandardLayoutType.html">标准布局类型</a>,那么在任何编译器上检验其公共子序列都有良好定义。</p>
|
|
<h4><span class="mw-headline" id=".E6.88.90.E5.91.98.E7.94.9F.E5.AD.98.E6.9C.9F">成员生存期</span></h4>
|
|
<p>联合体成员的<a href="cpp-language-lifetime.html">生存期</a>从该成员被设为活跃(active)时开始。如果之前已经有另一成员活跃,那么它的生存期终止。</p>
|
|
<p>当联合体的活跃成员通过形式为 <code>E1 = E2</code> 的复制表达式(使用内建赋值运算符或平凡的赋值运算符)切换时,对于 <code>E1</code> 中的各个成员访问和数组下标子表达式中出现的,其类型并非拥有非平凡或弃置的默认构造函数的类的每个联合体成员 X,如果 X 的修改在类型别名使用规则下会具有未定义行为,那么在所指名的存储中隐式创建一个 X 类型的对象;不进行初始化,且其生存期的开始按顺序晚于其左右的操作数的值计算,而早于赋值。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">union</span> A <span class="br0">{</span> <span class="kw4">int</span> x<span class="sy4">;</span> <span class="kw4">int</span> y<span class="br0">[</span><span class="nu0">4</span><span class="br0">]</span><span class="sy4">;</span> <span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw1">struct</span> B <span class="br0">{</span> A a<span class="sy4">;</span> <span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw1">union</span> C <span class="br0">{</span> B b<span class="sy4">;</span> <span class="kw4">int</span> k<span class="sy4">;</span> <span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw4">int</span> f<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
|
|
C c<span class="sy4">;</span> <span class="co1">// 不开始任何联合体成员的生存期</span>
|
|
c.<span class="me1">b</span>.<span class="me1">a</span>.<span class="me1">y</span><span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span> <span class="sy1">=</span> <span class="nu0">4</span><span class="sy4">;</span> <span class="co1">// OK:"c.b.a.y[3]" 指名联合体成员 c.b 与 c.b.a.y;</span>
|
|
<span class="co1">// 这创建对象以保有联合体成员 c.b 和 c.b.a.y</span>
|
|
<span class="kw1">return</span> c.<span class="me1">b</span>.<span class="me1">a</span>.<span class="me1">y</span><span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span><span class="sy4">;</span> <span class="co1">// OK:c.b.a.y 指代新创建的对象</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="kw1">struct</span> X <span class="br0">{</span> <span class="kw4">const</span> <span class="kw4">int</span> a<span class="sy4">;</span> <span class="kw4">int</span> b<span class="sy4">;</span> <span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw1">union</span> Y <span class="br0">{</span> X x<span class="sy4">;</span> <span class="kw4">int</span> k<span class="sy4">;</span> <span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw4">void</span> g<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
|
|
Y y <span class="sy1">=</span> <span class="br0">{</span> <span class="br0">{</span> <span class="nu0">1</span>, <span class="nu0">2</span> <span class="br0">}</span> <span class="br0">}</span><span class="sy4">;</span> <span class="co1">// OK,y.x 是联合体的活跃成员</span>
|
|
<span class="kw4">int</span> n <span class="sy1">=</span> y.<span class="me1">x</span>.<span class="me1">a</span><span class="sy4">;</span>
|
|
y.<span class="me1">k</span> <span class="sy1">=</span> <span class="nu0">4</span><span class="sy4">;</span> <span class="co1">// OK:结束 y.x 的生存期,y.k 是联合体的活跃成员</span>
|
|
y.<span class="me1">x</span>.<span class="me1">b</span> <span class="sy1">=</span> n<span class="sy4">;</span> <span class="co1">// 未定义行为:y.x.b 在其生存期外被修改,</span>
|
|
<span class="co1">// "y.x.b" 指名 y.x,但 X 的默认构造函数被弃置,</span>
|
|
<span class="co1">// 所以联合体成员 y.x 的生存期不会隐式开始</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<p>联合体类型的平凡<span class="t-rev-inl t-since-cxx11"><span>移动构造函数、移动赋值运算符、</span> <span><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></span></span>复制构造函数和复制赋值运算符复制对象表示。如果源与目标不是同一对象,那么这些特殊成员函数在复制前开始每个内嵌于目标的并对应内嵌于源的对象(除了既非目标的子对象亦不拥有<a href="cpp-language-lifetime.html#.E9.9A.90.E5.BC.8F.E7.94.9F.E5.AD.98.E6.9C.9F.E7.B1.BB.E5.9E.8B">隐式生存期类型</a>的对象)的生存期。否则,它们不做任何事。在经由平凡特殊成员函数构造或赋值后,两个联合体对象拥有相同的对应活跃成员(如果存在)。</p>
|
|
<h4><span class="mw-headline" id=".E5.8C.BF.E5.90.8D.E8.81.94.E5.90.88.E4.BD.93">匿名联合体</span></h4>
|
|
<p><i>匿名联合体</i>是不同时定义任何变量(包括联合体类型的对象、引用或指向联合体的指针)的无名的联合体定义。</p>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td class="t-sdsc-nopad"><code><b>union</b></code> <code><b>{</b></code> <span class="t-spar">成员说明</span> <code><b>}</b></code> <code><b>;</b></code></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<p>匿名联合体有更多限制:它们不能有成员函数,不能有静态数据成员,且所有数据成员必须公开。只能声明非静态数据成员<span class="t-rev-inl t-since-cxx11"><span>,外加<a href="cpp-language-static_assert.html"><code>static_assert</code></a> 声明</span> <span><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></span></span>。</p>
|
|
<p>匿名联合体的成员被注入到它的外围作用域中(而且不得与其中声明的其他名字冲突)。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
<span class="kw1">union</span>
|
|
<span class="br0">{</span>
|
|
<span class="kw4">int</span> a<span class="sy4">;</span>
|
|
<span class="kw4">const</span> <span class="kw4">char</span><span class="sy2">*</span> p<span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
a <span class="sy1">=</span> <span class="nu0">1</span><span class="sy4">;</span>
|
|
p <span class="sy1">=</span> <span class="st0">"Jennifer"</span><span class="sy4">;</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<p>命名空间作用域的匿名联合体必须声明为 static,除非它们在无名命名空间出现。</p>
|
|
<h4><span class="mw-headline" id=".E8.81.94.E5.90.88.E4.BD.93.E5.BC.8F.E7.9A.84.E7.B1.BB">联合体式的类</span></h4>
|
|
<p><i>联合体式的类(union-like class)</i>是联合体,或是至少拥有一个匿名联合体成员的(非联合)类。联合体式的类拥有一组<i>变体成员(variant member)</i>:</p>
|
|
<ul>
|
|
<li>其成员匿名联合体的非静态数据成员;</li>
|
|
<li>另外,如果联合体式的类是联合体,则为其并非匿名联合体的非静态数据成员。</li>
|
|
</ul>
|
|
<p>联合体式的类可用于实现<a href="https://en.wikipedia.org/wiki/Tagged_union" class="extiw" title="enwiki:Tagged union">带标签联合体(tagged union)</a>。</p>
|
|
<div class="t-example">
|
|
<div class="t-example-live-link"></div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co2">#include <iostream></span>
|
|
|
|
<span class="co1">// S 拥有一个非静态数据成员(tag),三个枚举项成员(CHAR、INT、DOUBLE),</span>
|
|
<span class="co1">// 和三个变体成员(c、i、d)</span>
|
|
<span class="kw1">struct</span> S
|
|
<span class="br0">{</span>
|
|
<span class="kw2">enum</span><span class="br0">{</span>CHAR, INT, DOUBLE<span class="br0">}</span> tag<span class="sy4">;</span>
|
|
<span class="kw1">union</span>
|
|
<span class="br0">{</span>
|
|
<span class="kw4">char</span> c<span class="sy4">;</span>
|
|
<span class="kw4">int</span> i<span class="sy4">;</span>
|
|
<span class="kw4">double</span> d<span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
|
|
<span class="kw4">void</span> print_s<span class="br0">(</span><span class="kw4">const</span> S<span class="sy3">&</span> s<span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
<span class="kw1">switch</span><span class="br0">(</span>s.<span class="me1">tag</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
<span class="kw1">case</span> S<span class="sy4">::</span><span class="me2">CHAR</span><span class="sy4">:</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> s.<span class="me1">c</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="kw1">break</span><span class="sy4">;</span>
|
|
<span class="kw1">case</span> S<span class="sy4">::</span><span class="me2">INT</span><span class="sy4">:</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> s.<span class="me1">i</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="kw1">break</span><span class="sy4">;</span>
|
|
<span class="kw1">case</span> S<span class="sy4">::</span><span class="me2">DOUBLE</span><span class="sy4">:</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> s.<span class="me1">d</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="kw1">break</span><span class="sy4">;</span>
|
|
<span class="br0">}</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
S s <span class="sy1">=</span> <span class="br0">{</span>S<span class="sy4">::</span><span class="me2">CHAR</span>, <span class="st0">'a'</span><span class="br0">}</span><span class="sy4">;</span>
|
|
print_s<span class="br0">(</span>s<span class="br0">)</span><span class="sy4">;</span>
|
|
s.<span class="me1">tag</span> <span class="sy1">=</span> S<span class="sy4">::</span><span class="me2">INT</span><span class="sy4">;</span>
|
|
s.<span class="me1">i</span> <span class="sy1">=</span> <span class="nu0">123</span><span class="sy4">;</span>
|
|
print_s<span class="br0">(</span>s<span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<p>输出:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="text source-text">
|
|
<pre class="de1">a
|
|
123</pre></div>
|
|
</div>
|
|
</div>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx17">
|
|
<td>
|
|
<p>C++ 标准库包含 <span class="t-lc"><a href="cpp-utility-variant.html">std::variant</a></span>,它可以取代联合体和联合体式的类的大多数用途。上例可重写为</p>
|
|
<div class="t-example">
|
|
<div class="t-example-live-link"></div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co2">#include <variant></span>
|
|
<span class="co2">#include <iostream></span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
<a href="cpp-utility-variant.html"><span class="kw1085">std::<span class="me2">variant</span></span></a><span class="sy1"><</span><span class="kw4">char</span>, <span class="kw4">int</span>, <span class="kw4">double</span><span class="sy1">></span> s <span class="sy1">=</span> <span class="st0">'a'</span><span class="sy4">;</span>
|
|
<a href="cpp-utility-variant-visit.html"><span class="kw1086">std::<span class="me2">visit</span></span></a><span class="br0">(</span><span class="br0">[</span><span class="br0">]</span><span class="br0">(</span><span class="kw4">auto</span> x<span class="br0">)</span><span class="br0">{</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> x <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span><span class="br0">}</span>, s<span class="br0">)</span><span class="sy4">;</span>
|
|
s <span class="sy1">=</span> <span class="nu0">123</span><span class="sy4">;</span>
|
|
<a href="cpp-utility-variant-visit.html"><span class="kw1086">std::<span class="me2">visit</span></span></a><span class="br0">(</span><span class="br0">[</span><span class="br0">]</span><span class="br0">(</span><span class="kw4">auto</span> x<span class="br0">)</span><span class="br0">{</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> x <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span><span class="br0">}</span>, s<span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<p>输出:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="text source-text">
|
|
<pre class="de1">a
|
|
123</pre></div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E7.BC.BA.E9.99.B7.E6.8A.A5.E5.91.8A">缺陷报告</span></h3>
|
|
<p>下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。</p>
|
|
<table class="dsctable" style="font-size:0.8em">
|
|
<tr>
|
|
<th>DR</th>
|
|
<th>应用于</th>
|
|
<th>出版时的行为</th>
|
|
<th>正确行为</th>
|
|
</tr>
|
|
<tr>
|
|
<td><a rel="nofollow" class="external text" href="https://wg21.cmeerw.net/cwg/issue1940">CWG 1940</a></td>
|
|
<td>C++11</td>
|
|
<td>匿名联合体只允许非静态数据成员</td>
|
|
<td>也允许 <code>static_assert</code></td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E5.8F.82.E9.98.85">参阅</span></h3>
|
|
<table class="t-dsc-begin"></table>
|
|
</div>
|
|
<div class="visualClear"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|