372 lines
43 KiB
HTML
372 lines
43 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_aggregate_initialization 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>从花括号初始化器列表初始化聚合体。</p>
|
|
<h3><span class="mw-headline" id=".E8.AF.AD.E6.B3.95">语法</span></h3>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><span class="t-spar">T</span> <span class="t-spar">对象</span> <code><b>=</b></code> <code><b>{</b></code><span class="t-spar">实参1, 实参2, ...</span><code><b>}</b></code><code><b>;</b></code></td>
|
|
<td>(1)</td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><span class="t-spar">T</span> <span class="t-spar">对象</span> <code><b>{</b></code><span class="t-spar">实参1, 实参2, ...</span> <code><b>}</b></code><code><b>;</b></code></td>
|
|
<td>(2)</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><span class="t-spar">T</span> <span class="t-spar">对象</span> <code><b>=</b></code> <code><b>{</b></code> <code><b>.</b></code><span class="t-spar">指派符</span> <code><b>=</b></code> <span class="t-spar">实参1</span> <code><b>,</b></code> <code><b>.</b></code><span class="t-spar">指派符</span> <code><b>{</b></code> <span class="t-spar">实参2</span> <code><b>}</b></code> ... <code><b>}</b></code><code><b>;</b></code></td>
|
|
<td>(3)</td>
|
|
<td><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><span class="t-spar">T</span> <span class="t-spar">对象</span> <code><b>{</b></code> <code><b>.</b></code><span class="t-spar">指派符</span> <code><b>=</b></code> <span class="t-spar">实参1</span> <code><b>,</b></code> <code><b>.</b></code><span class="t-spar">指派符</span> <code><b>{</b></code> <span class="t-spar">实参2</span> <code><b>}</b></code> ... <code><b>}</b></code><code><b>;</b></code></td>
|
|
<td>(4)</td>
|
|
<td><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><span class="t-spar">T</span> <span class="t-spar">对象</span> <code><b>(</b></code><span class="t-spar">实参1, 实参2, ...</span><code><b>)</b></code><code><b>;</b></code></td>
|
|
<td>(5)</td>
|
|
<td><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E8.A7.A3.E9.87.8A">解释</span></h3>
|
|
<p>聚合初始化对<i>聚合体</i>进行初始化。<span class="t-rev-inl t-since-cxx11"><span>它是<a href="cpp-language-list_initialization.html">列表初始化</a></span> <span><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></span></span><span class="t-rev-inl t-since-cxx20"><span>,或<a href="cpp-language-direct_initialization.html">直接初始化</a></span> <span><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></span></span>的一种形式。</p>
|
|
<p>聚合体是下列类型之一:</p>
|
|
<ul>
|
|
<li>数组类型</li>
|
|
<li>符合以下条件的类类型(常为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw1">struct</span></span></span> 或 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw1">union</span></span></span>)</li>
|
|
</ul>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>没有私有或受保护的<span class="t-rev-inl t-since-cxx17"><span>直接</span> <span><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></span></span>非静态数据成员</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-until-cxx11">
|
|
<td>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>没有用户声明的构造函数</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
</td>
|
|
<td><span class="t-mark-rev t-until-cxx11">(C++11 前)</span></td>
|
|
</tr>
|
|
<tr class="t-rev t-since-cxx11 t-until-cxx17">
|
|
<td>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>没有用户提供的构造函数(允许显式预置或弃置的构造函数)</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span><br />
|
|
<span class="t-mark-rev t-until-cxx17">(C++17 前)</span></td>
|
|
</tr>
|
|
<tr class="t-rev t-since-cxx17 t-until-cxx20">
|
|
<td>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>没有用户提供、继承或 explicit 的构造函数(允许显式预置或弃置的构造函数)</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx17">(C++17 起)</span><br />
|
|
<span class="t-mark-rev t-until-cxx20">(C++20 前)</span></td>
|
|
</tr>
|
|
<tr class="t-rev t-since-cxx20">
|
|
<td>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>没有用户声明或继承的构造函数</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>没有<span class="t-rev-inl t-since-cxx17"><span>虚、私有或受保护</span> <span><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></span></span>的基类</li>
|
|
<li>没有虚成员函数</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx11 t-until-cxx14">
|
|
<td>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>没有<a href="cpp-language-data_members.html#.E6.88.90.E5.91.98.E5.88.9D.E5.A7.8B.E5.8C.96">默认成员初始化器</a></li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span><br />
|
|
<span class="t-mark-rev t-until-cxx14">(C++14 前)</span></td>
|
|
</tr>
|
|
</table>
|
|
<p>聚合初始化的效果是:</p>
|
|
<ul>
|
|
<li>每个<span class="t-rev-inl t-since-cxx17"><span>直接公开基类、</span> <span><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></span></span>数组元素或非静态类成员,以数组下标/出现于类定义的顺序,从初始化器列表中的对应子句进行<a href="cpp-language-copy_initialization.html">复制初始化</a>。</li>
|
|
</ul>
|
|
<ul>
|
|
<li>如果初始化器子句是表达式,那么根据复制初始化允许进行隐式转换<span class="t-rev-inl t-since-cxx11"><span>,但对于<a href="cpp-language-list_initialization.html">列表初始化</a>形式禁止窄化转换</span> <span><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></span></span>。</li>
|
|
</ul>
|
|
<ul>
|
|
<li>如果初始化器子句是嵌套的花括号初始化器列表(它不是表达式),那么它对应的数组元素/类成员<span class="t-rev-inl t-since-cxx17"><span>/公开基类</span> <span><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></span></span>从该子句进行<a href="cpp-language-list_initialization.html">列表初始化</a>:聚合初始化是递归的。</li>
|
|
</ul>
|
|
<ul>
|
|
<li>如果对象是未知大小的数组,且所提供的花括号环绕的初始化器列表拥有 <code>n</code> 个子句,那么该数组的大小是 <code>n</code>。(注意此时对象不能是非静态数据成员:成员必须拥有完整类型。)</li>
|
|
</ul>
|
|
<ul>
|
|
<li>静态数据成员和无名位域在聚合初始化中被跳过。</li>
|
|
</ul>
|
|
<ul>
|
|
<li>如果初始化器子句的数量超出所要初始化的成员<span class="t-rev-inl t-since-cxx17"><span>和基类</span> <span><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></span></span>的数量,那么程序非良构。</li>
|
|
</ul>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-until-cxx11">
|
|
<td>
|
|
<ul>
|
|
<li>如果初始化器子句的数量少于成员的数量,或初始化器列表完全为空,那么剩余成员被<a href="cpp-language-value_initialization.html">值初始化</a>。如果这些剩余成员的类型中有引用类型,那么程序非良构。</li>
|
|
</ul>
|
|
</td>
|
|
<td><span class="t-mark-rev t-until-cxx11">(C++11 前)</span></td>
|
|
</tr>
|
|
<tr class="t-rev t-since-cxx11">
|
|
<td>
|
|
<ul>
|
|
<li>如果初始化器子句的数量少于成员<span class="t-rev-inl t-since-cxx17"><span>和基类</span> <span><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></span></span>的数量,或初始化器列表完全为空,那么剩余成员<span class="t-rev-inl t-since-cxx17"><span>和基类</span> <span><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></span></span>会按照通常的<a href="cpp-language-list_initialization.html">列表初始化</a>规则(对非类类型和拥有默认构造函数的非聚合类进行值初始化,并对聚合体进行聚合初始化),<span class="t-rev-inl t-since-cxx14"><span>在类定义中有提供<a href="cpp-language-data_members.html#.E6.88.90.E5.91.98.E5.88.9D.E5.A7.8B.E5.8C.96">默认成员初始化器</a>的情况下用它初始化,否则</span> <span><span class="t-mark-rev t-since-cxx14">(C++14 起)</span></span></span>从空列表复制初始化。如果这些剩余成员的类型中有引用类型,那么程序非良构。</li>
|
|
</ul>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<ul>
|
|
<li>当聚合初始化联合体时,只初始化其首个非静态数据成员。</li>
|
|
</ul>
|
|
<p>可消除(省略)环绕嵌套的初始化器列表的花括号,这种情况下,使用所需数量的初始化器子句初始化对应的子聚合体的各个成员或元素,而后继的各个初始化器子句被用于初始化对象中的后续成员。然而,如果对象拥有不带任何成员的子聚合体(空结构体,或只保有静态成员的结构体),则不允许消除花括号而必须使用一个空的嵌套列表 <code><b>{}</b></code>。</p>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx20">
|
|
<td>
|
|
<h3><span class="mw-headline" id=".E6.8C.87.E6.B4.BE.E5.88.9D.E5.A7.8B.E5.8C.96.E5.99.A8">指派初始化器</span></h3>
|
|
<p>语法形式 <span class="t-v">(3,4)</span> 被称为指派初始化器:每个 <span class="t-spar">指派符</span> 必须指名 T 的一个直接非静态数据成员,而表达式中所用的所有 <span class="t-spar">指派符</span> 必须按照与 T 的数据成员相同的顺序出现。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">struct</span> A <span class="br0">{</span> <span class="kw4">int</span> x<span class="sy4">;</span> <span class="kw4">int</span> y<span class="sy4">;</span> <span class="kw4">int</span> z<span class="sy4">;</span> <span class="br0">}</span><span class="sy4">;</span>
|
|
A a<span class="br0">{</span>.<span class="me1">y</span> <span class="sy1">=</span> <span class="nu0">2</span>, .<span class="me1">x</span> <span class="sy1">=</span> <span class="nu0">1</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 错误:指派符的顺序不匹配声明顺序</span>
|
|
A b<span class="br0">{</span>.<span class="me1">x</span> <span class="sy1">=</span> <span class="nu0">1</span>, .<span class="me1">z</span> <span class="sy1">=</span> <span class="nu0">2</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// OK:b.y 被初始化为 0</span></pre></div>
|
|
</div>
|
|
<p>指派初始化器所指名的每个直接非静态数据成员,从其指派符后随的对应花括号或等号初始化器初始化。禁止窄化转换。</p>
|
|
<p>指派初始化器可用于将<a href="cpp-language-union.html">联合体</a>初始化为其首个成员之外的状态。只可以为一个联合体提供一个初始化器。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">union</span> u <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> b<span class="sy4">;</span> <span class="br0">}</span><span class="sy4">;</span>
|
|
u f <span class="sy1">=</span> <span class="br0">{</span> .<span class="me1">b</span> <span class="sy1">=</span> <span class="st0">"asdf"</span> <span class="br0">}</span><span class="sy4">;</span> <span class="co1">// OK:联合体的活跃成员为 b</span>
|
|
u g <span class="sy1">=</span> <span class="br0">{</span> .<span class="me1">a</span> <span class="sy1">=</span> <span class="nu0">1</span>, .<span class="me1">b</span> <span class="sy1">=</span> <span class="st0">"asdf"</span> <span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 错误:只可提供一个初始化器</span></pre></div>
|
|
</div>
|
|
<p>对于非联合体的聚合体中未提供指派初始化器的元素,按上述针对初始化器子句的数量少于成员数量时的规则进行初始化(如果提供默认成员初始化器则使用它,否则为空列表初始化):</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">struct</span> A <span class="br0">{</span>
|
|
string a<span class="sy4">;</span>
|
|
<span class="kw4">int</span> b <span class="sy1">=</span> <span class="nu0">42</span><span class="sy4">;</span>
|
|
<span class="kw4">int</span> c <span class="sy1">=</span> <span class="sy2">-</span><span class="nu0">1</span><span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
A<span class="br0">{</span>.<span class="me1">c</span><span class="sy1">=</span><span class="nu0">21</span><span class="br0">}</span> <span class="co1">// 以 {} 初始化 a,这样会调用默认构造函数</span>
|
|
<span class="co1">// 然后以 = 42 初始化 b</span>
|
|
<span class="co1">// 然后以 = 21 初始化 c</span></pre></div>
|
|
</div>
|
|
<p>如果以指派初始化器子句初始化的聚合体拥有一个匿名联合体成员,那么对应的指派初始化器必须指名该匿名联合体的其中一个成员。</p>
|
|
<p>注意:乱序的指派初始化、嵌套的指派初始化、指派初始化器与常规初始化器的混合,以及数组的指派初始化在 <a href="c-language-struct_initialization.html">C 编程语言</a>中受支持,但在 C++ 不允许。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">struct</span> A <span class="br0">{</span> <span class="kw4">int</span> x, y<span class="sy4">;</span> <span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw1">struct</span> B <span class="br0">{</span> <span class="kw1">struct</span> A a<span class="sy4">;</span> <span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw1">struct</span> A a <span class="sy1">=</span> <span class="br0">{</span>.<span class="me1">y</span> <span class="sy1">=</span> <span class="nu0">1</span>, .<span class="me1">x</span> <span class="sy1">=</span> <span class="nu0">2</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 合法 C,非法 C++(乱序)</span>
|
|
<span class="kw4">int</span> arr<span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span> <span class="sy1">=</span> <span class="br0">{</span><span class="br0">[</span><span class="nu0">1</span><span class="br0">]</span> <span class="sy1">=</span> <span class="nu0">5</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 合法 C,非法 C++(数组)</span>
|
|
<span class="kw1">struct</span> B b <span class="sy1">=</span> <span class="br0">{</span>.<span class="me1">a</span>.<span class="me1">x</span> <span class="sy1">=</span> <span class="nu0">0</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 合法 C,非法 C++(嵌套)</span>
|
|
<span class="kw1">struct</span> A a <span class="sy1">=</span> <span class="br0">{</span>.<span class="me1">x</span> <span class="sy1">=</span> <span class="nu0">1</span>, <span class="nu0">2</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 合法 C,非法 C++(混合)</span></pre></div>
|
|
</div>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E5.AD.97.E7.AC.A6.E6.95.B0.E7.BB.84">字符数组</span></h3>
|
|
<p>通常字符类型(<span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">char</span></span></span>、 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">signed</span> <span class="kw4">char</span></span></span>、 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">unsigned</span> <span class="kw4">char</span></span></span>)<span class="t-rev-inl t-since-cxx20"><span>、 <span class="t-c"><span class="mw-geshi cpp source-cpp">char8_t</span></span></span> <span><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></span></span><span class="t-rev-inl t-since-cxx11"><span>、 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">char16_t</span></span></span>、 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">char32_t</span></span></span></span> <span><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></span></span>或 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">wchar_t</span></span></span> 的数组能分别从通常<a href="cpp-language-string_literal.html">字符串字面量</a><span class="t-rev-inl t-since-cxx20"><span>、 UTF-8 字符串字面量</span> <span><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></span></span><span class="t-rev-inl t-since-cxx11"><span>、 UTF-16 字符串字面量、 UTF-32 字符串字面量</span> <span><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></span></span>或宽字符串字面量初始化,可以以花括号环绕。字符串字面量的相继字符(包含隐含的空终止字符)初始化各数组元素。如果数组大小被指定且大于字符串字面量中的字符数,那么剩余字符会被零初始化。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw4">char</span> a<span class="br0">[</span><span class="br0">]</span> <span class="sy1">=</span> <span class="st0">"abc"</span><span class="sy4">;</span>
|
|
<span class="co1">// 等价于 char a[4] = {'a', 'b', 'c', '\0'};</span>
|
|
|
|
<span class="co1">// unsigned char b[3] = "abc"; // 错误:初始化器字符串太长</span>
|
|
<span class="kw4">unsigned</span> <span class="kw4">char</span> b<span class="br0">[</span><span class="nu0">5</span><span class="br0">]</span><span class="br0">{</span><span class="st0">"abc"</span><span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="co1">// 等价于 unsigned char b[5] = {'a', 'b', 'c', '\0', '\0'};</span>
|
|
|
|
<span class="kw4">wchar_t</span> c<span class="br0">[</span><span class="br0">]</span> <span class="sy1">=</span> <span class="br0">{</span>L<span class="st0">"кошка"</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 可选的花括号</span>
|
|
<span class="co1">// 等价于 wchar_t c[6] = {L'к', L'о', L'ш', L'к', L'а', L'\0'};</span></pre></div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E6.B3.A8.E8.A7.A3">注解</span></h3>
|
|
<p>聚合类或数组可以包含非聚合的<span class="t-rev-inl t-since-cxx17"><span>公开基类、</span> <span><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></span></span>成员或元素,它们以上述方式初始化(例如从对应的初始化器子句复制初始化)</p>
|
|
<p>C++11 前,聚合初始化中曾允许窄化转换,但此后不再被允许,但从 C++20 起聚合初始化使用圆括号时允许它们。</p>
|
|
<p>C++11 前,由于语法限制,聚合初始化只能用于变量定义,而不能用于<a href="cpp-language-constructor.html">构造函数初始化器列表</a>、 <a href="cpp-language-new.html">new 表达式</a>或临时对象创建。</p>
|
|
<p>C 中,长度比字符串字面量的大小少一的字符数组可以从字符串字面量初始化;产生的数组是非空终止的。这在 C++ 中不允许。</p>
|
|
<h3><span class="mw-headline" id=".E7.A4.BA.E4.BE.8B">示例</span></h3>
|
|
<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 <string></span>
|
|
<span class="co2">#include <array></span>
|
|
<span class="kw1">struct</span> S <span class="br0">{</span>
|
|
<span class="kw4">int</span> x<span class="sy4">;</span>
|
|
<span class="kw1">struct</span> Foo <span class="br0">{</span>
|
|
<span class="kw4">int</span> i<span class="sy4">;</span>
|
|
<span class="kw4">int</span> j<span class="sy4">;</span>
|
|
<span class="kw4">int</span> a<span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span><span class="sy4">;</span>
|
|
<span class="br0">}</span> b<span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
|
|
<span class="kw1">union</span> U <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> b<span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
S s1 <span class="sy1">=</span> <span class="br0">{</span> <span class="nu0">1</span>, <span class="br0">{</span> <span class="nu0">2</span>, <span class="nu0">3</span>, <span class="br0">{</span><span class="nu0">4</span>, <span class="nu0">5</span>, <span class="nu0">6</span><span class="br0">}</span> <span class="br0">}</span> <span class="br0">}</span><span class="sy4">;</span>
|
|
S s2 <span class="sy1">=</span> <span class="br0">{</span> <span class="nu0">1</span>, <span class="nu0">2</span>, <span class="nu0">3</span>, <span class="nu0">4</span>, <span class="nu0">5</span>, <span class="nu0">6</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 相同,但有花括号消除</span>
|
|
S s3<span class="br0">{</span><span class="nu0">1</span>, <span class="br0">{</span><span class="nu0">2</span>, <span class="nu0">3</span>, <span class="br0">{</span><span class="nu0">4</span>, <span class="nu0">5</span>, <span class="nu0">6</span><span class="br0">}</span> <span class="br0">}</span> <span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 相同,使用直接列表初始化语法</span>
|
|
S s4<span class="br0">{</span><span class="nu0">1</span>, <span class="nu0">2</span>, <span class="nu0">3</span>, <span class="nu0">4</span>, <span class="nu0">5</span>, <span class="nu0">6</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// CWG 1270 前错误:花括号消除仅允许与等号一起使用</span>
|
|
|
|
<span class="kw4">int</span> ar<span class="br0">[</span><span class="br0">]</span> <span class="sy1">=</span> <span class="br0">{</span><span class="nu0">1</span>,<span class="nu0">2</span>,<span class="nu0">3</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// ar 为 int[3]</span>
|
|
<span class="kw4">int</span> ab<span class="br0">[</span><span class="br0">]</span> <span class="br0">(</span><span class="nu0">1</span>, <span class="nu0">2</span>, <span class="nu0">3</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// (C++20) ab 为 int[3] </span>
|
|
<span class="co1">// char cr[3] = {'a', 'b', 'c', 'd'}; // 过多初始化器子句</span>
|
|
<span class="kw4">char</span> cr<span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span> <span class="sy1">=</span> <span class="br0">{</span><span class="st0">'a'</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 数组初始化为 {'a', '\0', '\0'}</span>
|
|
|
|
<span class="kw4">int</span> ar2d1<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span> <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="nu0">3</span>, <span class="nu0">4</span><span class="br0">}</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 完全花括号的 2D 数组: {1, 2}</span>
|
|
<span class="co1">// {3, 4}</span>
|
|
<span class="kw4">int</span> ar2d2<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span> <span class="sy1">=</span> <span class="br0">{</span><span class="nu0">1</span>, <span class="nu0">2</span>, <span class="nu0">3</span>, <span class="nu0">4</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 花括号消除: {1, 2}</span>
|
|
<span class="co1">// {3, 4}</span>
|
|
<span class="kw4">int</span> ar2d3<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span> <span class="sy1">=</span> <span class="br0">{</span><span class="br0">{</span><span class="nu0">1</span><span class="br0">}</span>, <span class="br0">{</span><span class="nu0">2</span><span class="br0">}</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 仅第一列: {1, 0}</span>
|
|
<span class="co1">// {2, 0}</span>
|
|
|
|
<a href="cpp-container-array.html"><span class="kw1268">std::<span class="me2">array</span></span></a><span class="sy1"><</span><span class="kw4">int</span>, <span class="nu0">3</span><span class="sy1">></span> std_ar2<span class="br0">{</span> <span class="br0">{</span><span class="nu0">1</span>,<span class="nu0">2</span>,<span class="nu0">3</span><span class="br0">}</span> <span class="br0">}</span><span class="sy4">;</span> <span class="co1">// std::array 是聚合体</span>
|
|
<a href="cpp-container-array.html"><span class="kw1268">std::<span class="me2">array</span></span></a><span class="sy1"><</span><span class="kw4">int</span>, <span class="nu0">3</span><span class="sy1">></span> std_ar1 <span class="sy1">=</span> <span class="br0">{</span><span class="nu0">1</span>, <span class="nu0">2</span>, <span class="nu0">3</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 可以消除花括号</span>
|
|
|
|
<span class="kw4">int</span> ai<span class="br0">[</span><span class="br0">]</span> <span class="sy1">=</span> <span class="br0">{</span> <span class="nu0">1</span>, <span class="nu16">2.0</span> <span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 从 double 到 int 的窄化转换:</span>
|
|
<span class="co1">// C++11 中错误,C++03 中 OK</span>
|
|
|
|
<a href="cpp-string-basic_string.html"><span class="kw1230">std::<span class="me2">string</span></span></a> ars<span class="br0">[</span><span class="br0">]</span> <span class="sy1">=</span> <span class="br0">{</span><a href="cpp-string-basic_string.html"><span class="kw1230">std::<span class="me2">string</span></span></a><span class="br0">(</span><span class="st0">"one"</span><span class="br0">)</span>, <span class="co1">// 复制初始化</span>
|
|
<span class="st0">"two"</span>, <span class="co1">// 转换,然后复制初始化</span>
|
|
<span class="br0">{</span><span class="st0">'t'</span>, <span class="st0">'h'</span>, <span class="st0">'r'</span>, <span class="st0">'e'</span>, <span class="st0">'e'</span><span class="br0">}</span> <span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 列表初始化</span>
|
|
|
|
U u1 <span class="sy1">=</span> <span class="br0">{</span><span class="nu0">1</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// OK,联合体的首个成员</span>
|
|
<span class="co1">// U u2 = { 0, "asdf" }; // 错误:用过多的初始化器初始化联合体</span>
|
|
<span class="co1">// U u3 = { "asdf" }; // 错误:到 int 的转换无效</span>
|
|
|
|
<span class="br0">[</span><span class="br0">]</span><span class="br0">(</span><span class="kw4">auto</span>...<span class="br0">)</span> <span class="br0">{</span> <a href="cpp-io-c-puts.html"><span class="kw1830">std::<span class="me2">puts</span></span></a><span class="br0">(</span><span class="st0">"废弃无用的变量。。。 完成。"</span><span class="br0">)</span><span class="sy4">;</span> <span class="br0">}</span> <span class="br0">(</span>
|
|
s1, s2, s3, s4, ar, ab, cr, ar2d1, ar2d2, ar2d3, std_ar2, std_ar1, u1
|
|
<span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="co1">// 聚合体</span>
|
|
<span class="kw1">struct</span> base1 <span class="br0">{</span> <span class="kw4">int</span> b1, b2 <span class="sy1">=</span> <span class="nu0">42</span><span class="sy4">;</span> <span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="co1">// 非聚合体</span>
|
|
<span class="kw1">struct</span> base2 <span class="br0">{</span>
|
|
base2<span class="br0">(</span><span class="br0">)</span> <span class="sy4">:</span> b3<span class="br0">(</span><span class="nu0">42</span><span class="br0">)</span> <span class="br0">{</span><span class="br0">}</span>
|
|
<span class="kw4">int</span> b3<span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="co1">// C++17 里是聚合体</span>
|
|
<span class="kw1">struct</span> derived <span class="sy4">:</span> base1, base2 <span class="br0">{</span> <span class="kw4">int</span> d<span class="sy4">;</span> <span class="br0">}</span><span class="sy4">;</span>
|
|
derived d1<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="br0">}</span>, <span class="nu0">4</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// d1.b1 = 1, d1.b2 = 2, d1.b3 = 42, d1.d = 4</span>
|
|
derived d2<span class="br0">{</span> <span class="br0">{</span> <span class="br0">}</span>, <span class="br0">{</span> <span class="br0">}</span>, <span class="nu0">4</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// d2.b1 = 0, d2.b2 = 42, d2.b3 = 42, d2.d = 4</span></pre></div>
|
|
</div>
|
|
<p>输出:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="text source-text">
|
|
<pre class="de1">废弃无用的变量。。。 完成。</pre></div>
|
|
</div>
|
|
</div>
|
|
<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/issue1270">CWG 1270</a></td>
|
|
<td>C++11</td>
|
|
<td>仅允许在复制列表初始化中使用花括号消除</td>
|
|
<td>在别处也允许</td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E5.8F.82.E9.98.85">参阅</span></h3>
|
|
<ul>
|
|
<li><a href="cpp-language-copy_elision.html">复制消除</a></li>
|
|
<li><a href="cpp-language-initialization.html">初始化</a>
|
|
<ul>
|
|
<li><a href="cpp-language-constant_initialization.html">常量初始化</a></li>
|
|
<li><a href="cpp-language-list_initialization.html">列表初始化</a></li>
|
|
<li><a href="cpp-language-reference_initialization.html">引用初始化</a></li>
|
|
<li><a href="cpp-language-value_initialization.html">值初始化</a></li>
|
|
<li><a href="cpp-language-zero_initialization.html">零初始化</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
<table class="t-dsc-begin"></table>
|
|
</div>
|
|
<div class="visualClear"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|