271 lines
38 KiB
HTML
271 lines
38 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_array 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>
|
|
<p>数组声明是简单声明,其<a href="cpp-language-declarations.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"><span class="t-spar">非指针声明符</span> <code><b>[</b></code> <span class="t-spar">表达式</span><span class="t-mark">(可选)</span> <code><b>]</b></code> <span class="t-spar">属性</span><span class="t-mark">(可选)</span></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-spar">声明符</span>,但在以 <code>*</code>、<code>&</code> 或 <code>&&</code> 起始时必须用括号环绕。</td>
|
|
</tr>
|
|
<tr class="t-par">
|
|
<td><span class="t-spar">表达式</span></td>
|
|
<td>-</td>
|
|
<td>求值为大于零的值的<span class="t-rev-inl t-until-cxx14"><span><a href="cpp-language-constant_expression.html">整型常量表达式</a></span> <span><span class="t-mark-rev t-until-cxx14">(C++14 前)</span></span></span> <span class="t-rev-inl t-since-cxx14"><span><span class="t-lc"><a href="cpp-types-size_t.html">std::size_t</a></span> 类型的<a href="cpp-language-constant_expression.html">经转换常量表达式</a></span> <span><span class="t-mark-rev t-since-cxx14">(C++14 起)</span></span></span></td>
|
|
</tr>
|
|
<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>
|
|
</table>
|
|
<p>形式为 <span class="t-c"><span class="mw-geshi cpp source-cpp">T a<span class="br0">[</span>N<span class="br0">]</span><span class="sy4">;</span></span></span> 的声明,将 <code>a</code> 声明为由 <code>N</code> 个连续分配的 <code>T</code> 类型对象所组成的数组对象。数组元素拥有编号 <code>0, …, N - 1</code>,且可通过<a href="cpp-language-operator_member_access.html#.E5.86.85.E5.BB.BA.E7.9A.84.E4.B8.8B.E6.A0.87.E8.BF.90.E7.AE.97.E7.AC.A6">下标运算符 []</a> 访问,如 <span class="t-c"><span class="mw-geshi cpp source-cpp">a<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span></span></span>, …, <span class="t-c"><span class="mw-geshi cpp source-cpp">a<span class="br0">[</span>N <span class="sy2">-</span> <span class="nu0">1</span><span class="br0">]</span></span></span>。</p>
|
|
<p>数组可由任何(除 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">void</span></span></span> 外的)<a href="cpp-language-types.html">基础类型</a>、<a href="cpp-language-pointer.html">指针</a>、<a href="cpp-language-pointer.html">成员指针</a>、<a href="cpp-language-classes.html">类</a>、<a href="cpp-language-enum.html">枚举</a>,或从其他已知边界数组类型(这种情况下称数组是多维的)构成。换言之,只有除了未知边界数组以外的对象类型能成为数组类型的元素类型。拥有不完整元素类型的数组类型也是不完整类型。</p>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx11">
|
|
<td>
|
|
<p>能在数组的指针或引用的声明中以<span class="t-rev-inl t-since-cxx20"><span>可能<a href="cpp-language-constraints.html">受约束</a>的</span> <span><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></span></span> <a href="cpp-language-auto.html"><code>auto</code></a> 说明符为数组元素类型,这会从初始化器<span class="t-rev-inl t-since-cxx14"><span>或函数实参</span> <span><span class="t-mark-rev t-since-cxx14">(C++14 起)</span></span></span>推导元素类型,例如若 <code>a</code> 为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">int</span><span class="br0">[</span><span class="nu0">42</span><span class="br0">]</span></span></span> 类型左值则 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">auto</span> <span class="br0">(</span><span class="sy2">*</span>p<span class="br0">)</span><span class="br0">[</span><span class="nu0">42</span><span class="br0">]</span> <span class="sy1">=</span> <span class="sy3">&</span>a<span class="sy4">;</span></span></span> 合法。</p>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<p>不存在引用的数组或函数的数组。</p>
|
|
<p>对数组类型(通过 typedef 或模板操作)应用 <a href="cpp-language-cv.html">cv 限定符</a>,会将限定符应用到其元素类型,但元素为 cv 限定类型的任何数组类型,则被认为拥有相同的 cv 限定性。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co1">// a 与 b 拥有相同的 const 限定类型“含有 5 个 const char 元素的数组”</span>
|
|
<span class="kw1">typedef</span> <span class="kw4">const</span> <span class="kw4">char</span> CC<span class="sy4">;</span>
|
|
CC a<span class="br0">[</span><span class="nu0">5</span><span class="br0">]</span> <span class="sy1">=</span> <span class="br0">{</span><span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw1">typedef</span> <span class="kw4">char</span> CA<span class="br0">[</span><span class="nu0">5</span><span class="br0">]</span><span class="sy4">;</span>
|
|
<span class="kw4">const</span> CA b <span class="sy1">=</span> <span class="br0">{</span><span class="br0">}</span><span class="sy4">;</span></pre></div>
|
|
</div>
|
|
<p>在用于 <a href="cpp-language-new.html">new[] 表达式</a>时,数组的大小可以为零;这种数组无元素:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw4">int</span><span class="sy2">*</span> p <span class="sy1">=</span> new <span class="kw4">int</span><span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span><span class="sy4">;</span> <span class="co1">// 访问 p[0] 或 *p 是未定义的</span>
|
|
delete<span class="br0">[</span><span class="br0">]</span> p<span class="sy4">;</span> <span class="co1">// 仍然要求清理</span></pre></div>
|
|
</div>
|
|
<h4><span class="mw-headline" id=".E8.B5.8B.E5.80.BC">赋值</span></h4>
|
|
<p>数组类型的对象不能作为整体修改:虽然它们是<a href="cpp-language-value_category.html">左值</a>(即能取数组地址),但它们不能出现在赋值运算符的左侧:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw4">int</span> a<span class="br0">[</span><span class="nu0">3</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>, b<span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span> <span class="sy1">=</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="sy4">;</span>
|
|
<span class="kw4">int</span> <span class="br0">(</span><span class="sy2">*</span>p<span class="br0">)</span><span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span> <span class="sy1">=</span> <span class="sy3">&</span>a<span class="sy4">;</span> <span class="co1">// OK:能取地址</span>
|
|
a <span class="sy1">=</span> b<span class="sy4">;</span> <span class="co1">// 错误:a 是数组</span>
|
|
<span class="kw1">struct</span> <span class="br0">{</span> <span class="kw4">int</span> c<span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span><span class="sy4">;</span> <span class="br0">}</span> s1, s2 <span class="sy1">=</span> <span class="br0">{</span><span class="nu0">3</span>, <span class="nu0">4</span>, <span class="nu0">5</span><span class="br0">}</span><span class="sy4">;</span>
|
|
s1 <span class="sy1">=</span> s2<span class="sy4">;</span> <span class="co1">// OK:隐式定义的复制赋值运算符可对数组类型的数据成员赋值</span></pre></div>
|
|
</div>
|
|
<h4><span class="mw-headline" id=".E6.95.B0.E7.BB.84.E5.88.B0.E6.8C.87.E9.92.88.E7.9A.84.E9.80.80.E5.8C.96">数组到指针的退化</span></h4>
|
|
<p>存在从数组类型的左值和右值到指针类型的右值的<a href="cpp-language-implicit_conversion.html">隐式转换</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="co2">#include <numeric></span>
|
|
<span class="co2">#include <iterator></span>
|
|
|
|
<span class="kw4">void</span> g<span class="br0">(</span><span class="kw4">int</span> <span class="br0">(</span><span class="sy3">&</span>a<span class="br0">)</span><span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span><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> a<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="kw4">void</span> f<span class="br0">(</span><span class="kw4">int</span><span class="sy2">*</span> p<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> <span class="sy2">*</span>p <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
<span class="kw4">int</span> a<span class="br0">[</span><span class="nu0">3</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="kw4">int</span><span class="sy2">*</span> p <span class="sy1">=</span> a<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> sizeof a <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span> <span class="co1">// 打印数组的大小</span>
|
|
<span class="sy1"><<</span> sizeof p <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="co1">// 打印指针的大小</span>
|
|
|
|
<span class="co1">// 在可接受数组而不可接受指针的地方,只能使用数组</span>
|
|
g<span class="br0">(</span>a<span class="br0">)</span><span class="sy4">;</span> <span class="co1">// OK:函数以引用接受数组</span>
|
|
<span class="co1">// g(p); // 错误</span>
|
|
|
|
<span class="kw1">for</span><span class="br0">(</span><span class="kw4">int</span> n<span class="sy4">:</span> a<span class="br0">)</span> <span class="co1">// OK:数组可用于范围 for 循环</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> n <span class="sy1"><<</span> <span class="st0">' '</span><span class="sy4">;</span> <span class="co1">// 打印数组的各个元素</span>
|
|
<span class="co1">// for(int n: p) // 错误</span>
|
|
<span class="co1">// std::cout << n << ' ';</span>
|
|
|
|
<a href="cpp-algorithm-iota.html"><span class="kw1655">std::<span class="me2">iota</span></span></a><span class="br0">(</span><a href="cpp-iterator-begin.html"><span class="kw676">std::<span class="me2">begin</span></span></a><span class="br0">(</span>a<span class="br0">)</span>, <a href="cpp-iterator-end.html"><span class="kw680">std::<span class="me2">end</span></span></a><span class="br0">(</span>a<span class="br0">)</span>, <span class="nu0">7</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// OK:begin 与 end 接受数组</span>
|
|
<span class="co1">// std::iota(std::begin(p), std::end(p), 7); // 错误</span>
|
|
|
|
<span class="co1">// 在可接受指针而不可接受数组处的地方,两者都可以使用</span>
|
|
f<span class="br0">(</span>a<span class="br0">)</span><span class="sy4">;</span> <span class="co1">// OK:函数接受指针</span>
|
|
f<span class="br0">(</span>p<span class="br0">)</span><span class="sy4">;</span> <span class="co1">// OK:函数接受指针</span>
|
|
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="sy2">*</span>a <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span> <span class="co1">// 打印首元素</span>
|
|
<span class="sy1"><<</span> <span class="sy2">*</span>p <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span> <span class="co1">// 相同</span>
|
|
<span class="sy1"><<</span> <span class="sy2">*</span><span class="br0">(</span>a <span class="sy2">+</span> <span class="nu0">1</span><span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">' '</span> <span class="sy1"><<</span> a<span class="br0">[</span><span class="nu0">1</span><span class="br0">]</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span> <span class="co1">// 打印第二元素</span>
|
|
<span class="sy1"><<</span> <span class="sy2">*</span><span class="br0">(</span>p <span class="sy2">+</span> <span class="nu0">1</span><span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">' '</span> <span class="sy1"><<</span> p<span class="br0">[</span><span class="nu0">1</span><span class="br0">]</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="co1">// 相同</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
</div>
|
|
<h4><span class="mw-headline" id=".E5.A4.9A.E7.BB.B4.E6.95.B0.E7.BB.84">多维数组</span></h4>
|
|
<p>当数组的元素类型是另一数组时,称该数组是多维的:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co1">// 含有 2 个【含有 3 个 int 元素的数组】元素的数组</span>
|
|
<span class="kw4">int</span> a<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><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="nu0">2</span>, <span class="nu0">3</span><span class="br0">}</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="sy4">;</span> <span class="co1">// 可视作 2 × 3 矩阵,以行为主布局</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="kw4">int</span> a<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span class="sy4">;</span> <span class="co1">// 含有 2 个 int 元素的数组</span>
|
|
<span class="kw4">int</span><span class="sy2">*</span> p1 <span class="sy1">=</span> a<span class="sy4">;</span> <span class="co1">// 退化到指向 a 的首元素的指针</span>
|
|
|
|
<span class="kw4">int</span> b<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span><span class="sy4">;</span> <span class="co1">// 含有 2 个【含有 3 个 int 元素的数组】元素的数组</span>
|
|
<span class="co1">// int** p2 = b; // 错误:b 不退化到 int**</span>
|
|
<span class="kw4">int</span> <span class="br0">(</span><span class="sy2">*</span>p2<span class="br0">)</span><span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span> <span class="sy1">=</span> b<span class="sy4">;</span> <span class="co1">// b 退化到指向 b 的首个 3 元素行的指针</span>
|
|
|
|
<span class="kw4">int</span> c<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span class="br0">[</span><span class="nu0">3</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">// 含有 2 个【含有 3 个【含有 4 个 int 元素的数组】元素的数组】元素的数组</span>
|
|
<span class="co1">// int*** p3 = c; // 错误:c 不退化到 int***</span>
|
|
<span class="kw4">int</span> <span class="br0">(</span><span class="sy2">*</span>p3<span class="br0">)</span><span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span><span class="br0">[</span><span class="nu0">4</span><span class="br0">]</span> <span class="sy1">=</span> c<span class="sy4">;</span> <span class="co1">// c 退化到指向 c 首个 3 × 4 元素平面的指针</span></pre></div>
|
|
</div>
|
|
<h4><span class="mw-headline" id=".E6.9C.AA.E7.9F.A5.E8.BE.B9.E7.95.8C.E6.95.B0.E7.BB.84">未知边界数组</span></h4>
|
|
<p>如果在数组声明中省略 <span class="t-spar">表达式</span>,则声明的类型是“T 的未知边界数组”,这是一种<a href="cpp-language-type.html#.E4.B8.8D.E5.AE.8C.E6.95.B4.E7.B1.BB.E5.9E.8B">不完整类型</a>,除非在声明时带有<a href="cpp-language-aggregate_initialization.html">聚合初始化器</a>:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw4">extern</span> <span class="kw4">int</span> x<span class="br0">[</span><span class="br0">]</span><span class="sy4">;</span> <span class="co1">// x 的类型是“边界未知的含有 int 元素的数组”</span>
|
|
<span class="kw4">int</span> a<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">// a 的类型是“含有 3 个 int 元素的数组”</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="kw4">extern</span> <span class="kw4">int</span> a<span class="br0">[</span><span class="br0">]</span><span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span class="sy4">;</span> <span class="co1">// OK:边界未知的含有【含有 2 个 int 元素的数组】元素的数组</span>
|
|
<span class="kw4">extern</span> <span class="kw4">int</span> b<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span class="br0">[</span><span class="br0">]</span><span class="sy4">;</span> <span class="co1">// 错误:数组有不完整类型</span></pre></div>
|
|
</div>
|
|
<p>可以构成到未知边界数组的引用和指针,但不能从已知边界的数组或指向已知边界数组的指针对其初始化或赋值。注意在 C 编程语言中,指向未知边界数组的指针与指向已知边界数组的指针兼容,从而可以双向转换和赋值。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw4">extern</span> <span class="kw4">int</span> a1<span class="br0">[</span><span class="br0">]</span><span class="sy4">;</span>
|
|
<span class="kw4">int</span> <span class="br0">(</span><span class="sy3">&</span>r1<span class="br0">)</span><span class="br0">[</span><span class="br0">]</span> <span class="sy1">=</span> a1<span class="sy4">;</span> <span class="co1">// OK</span>
|
|
<span class="kw4">int</span> <span class="br0">(</span><span class="sy2">*</span>p1<span class="br0">)</span><span class="br0">[</span><span class="br0">]</span> <span class="sy1">=</span> <span class="sy3">&</span>a1<span class="sy4">;</span> <span class="co1">// OK</span>
|
|
<span class="kw4">int</span> <span class="br0">(</span><span class="sy2">*</span>q<span class="br0">)</span><span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span> <span class="sy1">=</span> <span class="sy3">&</span>a1<span class="sy4">;</span> <span class="co1">// 错误(但 C 中 OK)</span>
|
|
|
|
<span class="kw4">int</span> a2<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="kw4">int</span> <span class="br0">(</span><span class="sy3">&</span>r2<span class="br0">)</span><span class="br0">[</span><span class="br0">]</span> <span class="sy1">=</span> a2<span class="sy4">;</span> <span class="co1">// 错误</span>
|
|
<span class="kw4">int</span> <span class="br0">(</span><span class="sy2">*</span>p2<span class="br0">)</span><span class="br0">[</span><span class="br0">]</span> <span class="sy1">=</span> <span class="sy3">&</span>a2<span class="sy4">;</span> <span class="co1">// 错误(但 C 中 OK)</span></pre></div>
|
|
</div>
|
|
<p>指向未知边界数组的指针不能参与<a href="cpp-language-operator_arithmetic.html#.E5.8A.A0.E6.B3.95.E6.80.A7.E8.BF.90.E7.AE.97.E7.AC.A6">指针算术</a>且不能用在<a href="cpp-language-operator_member_access.html#.E5.86.85.E5.BB.BA.E7.9A.84.E4.B8.8B.E6.A0.87.E8.BF.90.E7.AE.97.E7.AC.A6">下标运算符</a>的左侧,但可以解引用。到未知边界数组的引用和指针无法作为<a href="cpp-language-function.html#.E5.BD.A2.E5.8F.82.E5.88.97.E8.A1.A8">函数形参</a>。</p>
|
|
<h4><span class="mw-headline" id=".E6.95.B0.E7.BB.84.E5.8F.B3.E5.80.BC">数组右值</span></h4>
|
|
<p>尽管数组无法从函数按值返回,且不能作为大多数转型表达式的目标,数组<a href="cpp-language-value_category.html">纯右值</a>依然可以通过使用类型别名构成,并用<a href="cpp-language-explicit_cast.html">花括号初始化的函数式转型</a>来构造数组的临时量。</p>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx17">
|
|
<td>
|
|
<p>与类的纯右值类似,数组的纯右值由<a href="cpp-language-implicit_conversion.html#.E4.B8.B4.E6.97.B6.E9.87.8F.E5.AE.9E.E8.B4.A8.E5.8C.96">临时量实质化</a>在求值时转换成亡值。</p>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<p>可以通过访问类右值的数组成员,<span class="t-lc">std::move</span> 或其他返回右值引用的转型或函数调用来直接构成数组的<a href="cpp-language-value_category.html">亡值</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="co2">#include <type_traits></span>
|
|
<span class="co2">#include <utility></span>
|
|
|
|
<span class="kw4">void</span> f<span class="br0">(</span><span class="kw4">int</span> <span class="br0">(</span><span class="sy3">&&</span>x<span class="br0">)</span><span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span><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> sizeof x <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="kw1">struct</span> X
|
|
<span class="br0">{</span>
|
|
<span class="kw4">int</span> i<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span><span class="sy4">;</span>
|
|
<span class="br0">}</span> x<span class="sy4">;</span>
|
|
|
|
<span class="kw1">template</span><span class="sy1"><</span><span class="kw1">typename</span> T<span class="sy1">></span> <span class="kw1">using</span> identity <span class="sy1">=</span> T<span class="sy4">;</span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><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> sizeof X<span class="br0">(</span><span class="br0">)</span>.<span class="me1">i</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="co1">// 数组的大小</span>
|
|
f<span class="br0">(</span>X<span class="br0">(</span><span class="br0">)</span>.<span class="me1">i</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// OK:绑定到亡值</span>
|
|
<span class="co1">// f(x.i); // 错误:不能绑定到左值</span>
|
|
|
|
<span class="kw4">int</span> a<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span><span class="sy4">;</span>
|
|
f<span class="br0">(</span>std<span class="sy4">::</span><span class="me2">move</span><span class="br0">(</span>a<span class="br0">)</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// OK:绑定到亡值</span>
|
|
|
|
<span class="kw1">using</span> arr_t <span class="sy1">=</span> <span class="kw4">int</span><span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span><span class="sy4">;</span>
|
|
f<span class="br0">(</span>arr_t<span class="br0">{</span><span class="br0">}</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// OK:绑定到纯右值</span>
|
|
f<span class="br0">(</span>identity<span class="sy1"><</span><span class="kw4">int</span><span class="br0">[</span><span class="br0">]</span><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="nu0">2</span>, <span class="nu0">3</span><span class="br0">}</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">// OK:绑定到纯右值</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">24
|
|
24
|
|
24
|
|
24
|
|
24</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/issue393">CWG 393</a></td>
|
|
<td>C++98</td>
|
|
<td>未知边界的数组或引用不能为函数形参</td>
|
|
<td>它能</td>
|
|
</tr>
|
|
<tr>
|
|
<td><a rel="nofollow" class="external text" href="https://wg21.cmeerw.net/cwg/issue2397">CWG 2397</a></td>
|
|
<td>C++11</td>
|
|
<td><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">auto</span></span></span> 不能用作元素类型</td>
|
|
<td>它能</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>
|