263 lines
35 KiB
HTML
263 lines
35 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_eval_order 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>求值任何表达式的任何部分,包括求值函数参数的顺序都是<i>未说明</i>的(除了下列的一些例外)。编译器能以任何顺序求值任何操作数和其他子表达式,并且可以在再次求值同一表达式时选择另一顺序。</p>
|
|
<p>C++ 中无从左到右或从右到左求值的概念。这不会与运算符的从左到右及从右到左结合性混淆:表达式 <code>a() + b() + c()</code> 由于 operator+ 的从左到右结合性被分析成 <code>(a() + b()) + c()</code> ,但在运行时可以首先、最后或者在 <code>a()</code> 和 <code>b()</code> 之间对 <code>c</code> 函数调用求值:</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 <cstdio></span>
|
|
<span class="kw4">int</span> a<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</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">"a"</span><span class="br0">)</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
<span class="kw4">int</span> b<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</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">"b"</span><span class="br0">)</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
<span class="kw4">int</span> c<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</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">"c"</span><span class="br0">)</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
<span class="kw4">void</span> z<span class="br0">(</span><span class="kw4">int</span>, <span class="kw4">int</span>, <span class="kw4">int</span><span class="br0">)</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>
|
|
z<span class="br0">(</span>a<span class="br0">(</span><span class="br0">)</span>, b<span class="br0">(</span><span class="br0">)</span>, c<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 允许全部 6 种输出排列</span>
|
|
<span class="kw1">return</span> a<span class="br0">(</span><span class="br0">)</span> <span class="sy2">+</span> b<span class="br0">(</span><span class="br0">)</span> <span class="sy2">+</span> c<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 允许全部 6 种输出排列</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">b
|
|
c
|
|
a
|
|
c
|
|
a
|
|
b</pre></div>
|
|
</div>
|
|
</div>
|
|
<p><br /></p>
|
|
<h2><span class="mw-headline" id=".E2.80.9C.E6.8C.89.E9.A1.BA.E5.BA.8F.E6.97.A9.E4.BA.8E.E2.80.9D.E8.A7.84.E5.88.99_.28C.2B.2B11_.E8.B5.B7.29">“按顺序早于”规则 <span class="t-mark-rev t-since-cxx11">(C++11 起)</span></span></h2>
|
|
<h3><span class="mw-headline" id=".E5.AE.9A.E4.B9.89">定义</span></h3>
|
|
<h4><span class="mw-headline" id=".E8.A1.A8.E8.BE.BE.E5.BC.8F.E6.B1.82.E5.80.BC">表达式求值</span></h4>
|
|
<p>每个表达式的求值包括:</p>
|
|
<ul>
|
|
<li><i>值计算</i>:计算表达式所返回的值。这可能涉及确定对象的身份(泛左值的求值,例如当表达式返回到某对象的引用时),或读取先前赋给对象的值(纯右值的求值,例如当表达式返回数或某个其他值时)</li>
|
|
<li>引发<i>副作用</i>:访问(读或写)<code>volatile</code> 泛左值所指代的对象,修改(写入)对象,调用库 I/O 函数,或调用任何做出这些操作的函数。</li>
|
|
</ul>
|
|
<h4><span class="mw-headline" id=".E9.A1.BA.E5.BA.8F">顺序</span></h4>
|
|
<p>“按顺序早于 (sequenced-before)”是同一线程中的求值之间的非对称的、传递的对偶关系。</p>
|
|
<ul>
|
|
<li>若 A 按顺序早于 B,则 A 的求值将在 B 的求值开始前完成。</li>
|
|
<li>若 A 不按顺序早于 B 而 B 按顺序早于 A,则 B 的求值将在 A 的求值开始前完成。</li>
|
|
<li>若 A 不按顺序早于 B 而 B 不按顺序早于 A,则存在两种可能:
|
|
<ul>
|
|
<li>A 与 B 的求值是无顺序 (unsequenced) 的:它们能以任何顺序进行,并可能重叠(在同一执行线程内,编译器可以将组成 A 与 B 的 CPU 指令交错)</li>
|
|
<li>A 与 B 的求值是顺序不确定 (indeterminately sequenced) 的:它们可以任意顺序进行但不可重叠,A 在 B 前完成,或 B 在 A 前完成。下次求值相同表达式时顺序可以相反。</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
<h3><span class="mw-headline" id=".E8.A7.84.E5.88.99">规则</span></h3>
|
|
<div class="t-li1"><span class="t-li">1)</span> 下列<i>全表达式</i>:
|
|
<ul>
|
|
<li><a href="cpp-language-expressions.html#.E4.B8.8D.E6.B1.82.E5.80.BC.E8.A1.A8.E8.BE.BE.E5.BC.8F">不求值操作数</a></li>
|
|
<li><a href="cpp-language-constant_expression.html">常量表达式</a></li>
|
|
</ul>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx20">
|
|
<td>
|
|
<ul>
|
|
<li><a href="cpp-language-consteval.html">立即调用</a></li>
|
|
</ul>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<ul>
|
|
<li>整个<a href="cpp-language-initialization.html">初始化器</a>,包含任何逗号分隔的成分表达式</li>
|
|
<li>在非临时对象生存期末尾生成的析构函数调用</li>
|
|
<li>不是其他全表达式一部分的表达式(例如整个<a href="cpp-language-statements.html#.E8.A1.A8.E8.BE.BE.E5.BC.8F.E8.AF.AD.E5.8F.A5">表达式语句</a>,<a href="cpp-language-for.html"><code>for</code></a>/<a href="cpp-language-while.html"><code>while</code></a> 循环的控制表达式,<a href="cpp-language-if.html"><code>if</code></a>/<a href="cpp-language-switch.html"><code>switch</code></a> 的条件表达式,<a href="cpp-language-return.html"><code>return</code></a> 语句中的表达式,等等),</li>
|
|
</ul>
|
|
</div>
|
|
<div class="t-li1"><span class="t-li"></span> 其值计算和副作用,包括应用到表达式结果的隐式转换,对临时量的析构函数调用,(初始化聚合体时)默认成员初始化器,和涉及函数调用的所有其他的语言构造,都<i>按顺序早于</i>下一个<i>全表达式</i>的每个值计算和副作用。</div>
|
|
<div class="t-li1"><span class="t-li">2)</span> 任何<a href="cpp-language-expressions.html#.E8.BF.90.E7.AE.97.E7.AC.A6">运算符</a>的各操作数的值计算(但非副作用)均<i>按顺序早于</i>该运算符结果的值计算(但非副作用)。</div>
|
|
<div class="t-li1"><span class="t-li">3)</span> 调用函数时(无论函数是否内联,且无论是否使用显式函数调用语法),与任何实参表达式或与指代被调用函数的后缀表达式关联的每个值计算和副作用,都<i>按顺序早于</i>被调用函数体内的每个表达式或语句的执行。</div>
|
|
<div class="t-li1"><span class="t-li">4)</span> 内建<a href="cpp-language-operator_incdec.html">后自增与后自减</a>运算符的值计算<i>按顺序早于</i>其副作用。</div>
|
|
<div class="t-li1"><span class="t-li">5)</span> 内建<a href="cpp-language-operator_incdec.html">前自增与前自减</a>运算符的副作用<i>按顺序早于</i>其值计算(作为由复合赋值的定义所致的隐含规则)。</div>
|
|
<div class="t-li1"><span class="t-li">6)</span> 内建<a href="cpp-language-operator_logical.html">逻辑</a>与 (AND) 运算符 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="sy3">&&</span></span></span> 和内建逻辑或 (OR) 运算符 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="sy3">||</span></span></span> 的第一(左)操作数的每个值计算和副作用,<i>按顺序早于</i>第二(右)操作数的每个值计算和副作用。</div>
|
|
<div class="t-li1"><span class="t-li">7)</span> 与<a href="cpp-language-operator_other.html#.E6.9D.A1.E4.BB.B6.E8.BF.90.E7.AE.97.E7.AC.A6">条件运算符</a> <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="sy4">?:</span></span></span> 中的第一个表达式关联的每个值计算和副作用,都<i>按顺序早于</i>与第二或第三表达式关联的每个值计算和副作用。</div>
|
|
<div class="t-li1"><span class="t-li">8)</span> 内建<a href="cpp-language-operator_assignment.html#.E5.86.85.E5.BB.BA.E7.9A.84.E7.9B.B4.E6.8E.A5.E8.B5.8B.E5.80.BC">赋值</a>运算符和所有内建<a href="cpp-language-operator_assignment.html#.E5.86.85.E5.BB.BA.E7.9A.84.E5.A4.8D.E5.90.88.E8.B5.8B.E5.80.BC">复合</a>赋值运算符的副作用(修改左参数),均<i>按顺序晚于</i>左右参数的值计算(但非副作用),且<i>按顺序早于</i>赋值表达式的值计算(即早于返回指代被修改对象的引用之时)。</div>
|
|
<div class="t-li1"><span class="t-li">9)</span> 内建<a href="cpp-language-operator_other.html#.E5.86.85.E5.BB.BA.E7.9A.84.E9.80.97.E5.8F.B7.E8.BF.90.E7.AE.97.E7.AC.A6">逗号运算符</a> <span class="t-c"><span class="mw-geshi cpp source-cpp">,</span></span> 的第一个(左)参数的每个值计算和副作用均<i>按顺序早于</i>第二个(右)参数的每个值计算和副作用。</div>
|
|
<div class="t-li1"><span class="t-li">10)</span> <a href="cpp-language-list_initialization.html">列表初始化</a>中,在大括号中用逗号分隔的任何给定的初始化器子句的每个值计算和副作用都<i>按顺序早于</i>逗号后的任何给定的初始化器子句的每个值计算和副作用</div>
|
|
<div class="t-li1"><span class="t-li">11)</span> 若某个函数调用既不<i>按顺序早于</i>又不<i>按顺序晚于</i>另一函数调用,则它们是<i>顺序不确定的</i>(程序必须表现为<a href="cpp-language-as_if.html">如同</a>组成不同函数调用的 CPU 指令决不会交错,即使函数被内联也是如此)。
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx17">
|
|
<td>
|
|
<p>规则 11 有一个例外:在 <a href="cpp-algorithm-execution_policy_tag_t.html"><tt>std::execution::par_unseq</tt></a> 执行策略下执行的标准库算法所作的函数调用是<i>无顺序的</i>,并且可以任意交错。</p>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="t-li1"><span class="t-li">12)</span> 对分配函数(<a href="cpp-memory-new-operator_new.html"><tt>operator new</tt></a>)的调用相对于 <a href="cpp-language-new.html">new 表达式</a>中构造函数参数的求值来说,<span class="t-rev-inl t-until-cxx17"><span>是顺序不确定的</span> <span><span class="t-mark-rev t-until-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>。</div>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx14">
|
|
<td>
|
|
<div class="t-li1"><span class="t-li">13)</span> 从函数返回时,作为求值函数调用结果的临时量的复制初始化<i>按顺序早于</i>在 <a href="cpp-language-return.html">return 语句</a>的操作数末尾处对所有临时量的销毁,而这些销毁进一步<i>按顺序早于</i>对环绕 return 语句的块的所有局部变量的销毁。</div>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx14">(C++14 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx17">
|
|
<td>
|
|
<div class="t-li1"><span class="t-li">14)</span> 函数调用表达式中,指名函数的表达式按顺序早于每个参数表达式和每个默认实参。</div>
|
|
<div class="t-li1"><span class="t-li">15)</span> 函数调用表达式中,每个形参的初始化的值计算和副作用相对于任何其他形参的初始化的值计算和副作用是顺序不确定的。</div>
|
|
<div class="t-li1"><span class="t-li">16)</span> 用运算符写法进行调用时,每个重载的运算符均遵循其所重载的内建运算符的定序规则。</div>
|
|
<div class="t-li1"><span class="t-li">17)</span> 下标表达式 <code>E1[E2]</code> 中,E1 的每个值计算和副作用均按顺序早于 E2 的每个值计算和副作用。</div>
|
|
<div class="t-li1"><span class="t-li">18)</span> 成员指针表达式 <code>E1.*E2</code> 或 <code>E1->*E2</code> 中,E1 的每个值计算和副作用都按顺序早于 E2 的每个值计算和副作用(除非 E1 的动态类型不含 E2 所指的成员)。</div>
|
|
<div class="t-li1"><span class="t-li">19)</span> 移位运算符表达式 <code>E1<<E2</code> 和 <code>E1>>E2</code> 中,E1 的每个值计算和副作用都按顺序早于 E2 的每个值计算和副作用。</div>
|
|
<div class="t-li1"><span class="t-li">20)</span> 每个简单赋值表达式 <code>E1=E2</code> 和每个复合赋值表达式 <code>E1@=E2</code> 中,E2 的每个值计算和副作用均按顺序早于 E1 的每个值计算和副作用。</div>
|
|
<div class="t-li1"><span class="t-li">21)</span> 带括号的初始化器中的逗号分隔的表达式列表中的每个表达式,如同函数调用一般求值(顺序不确定)。</div>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E6.9C.AA.E5.AE.9A.E4.B9.89.E8.A1.8C.E4.B8.BA">未定义行为</span></h3>
|
|
<p>1) 若标量对象上的一项副作用相对于同一标量对象上的另一副作用为无顺序,则<a href="cpp-language-ub.html">其行为未定义</a>。</p>
|
|
<p><span class="t-c"><span class="mw-geshi cpp source-cpp">i <span class="sy1">=</span> <span class="sy2">++</span>i <span class="sy2">+</span> <span class="nu0">2</span><span class="sy4">;</span> <span class="co1">// C++11 前为未定义行为</span><br />
|
|
i <span class="sy1">=</span> i<span class="sy2">++</span> <span class="sy2">+</span> <span class="nu0">2</span><span class="sy4">;</span> <span class="co1">// C++17 前为未定义行为</span><br />
|
|
f<span class="br0">(</span>i <span class="sy1">=</span> <span class="sy2">-</span><span class="nu0">2</span>, i <span class="sy1">=</span> <span class="sy2">-</span><span class="nu0">2</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// C++17 前为未定义行为</span><br />
|
|
f<span class="br0">(</span><span class="sy2">++</span>i, <span class="sy2">++</span>i<span class="br0">)</span><span class="sy4">;</span> <span class="co1">// C++17 前为未定义行为,C++17 起为未指明</span><br />
|
|
i <span class="sy1">=</span> <span class="sy2">++</span>i <span class="sy2">+</span> i<span class="sy2">++</span><span class="sy4">;</span> <span class="co1">// 未定义行为</span></span></span></p>
|
|
<p>2) 若标量对象上的副作用相对于使用同一标量对象的值的值计算为无顺序,则<a href="cpp-language-ub.html">其行为未定义</a>。</p>
|
|
<p><span class="t-c"><span class="mw-geshi cpp source-cpp">cout <span class="sy1"><<</span> i <span class="sy1"><<</span> i<span class="sy2">++</span><span class="sy4">;</span> <span class="co1">// C++17 前为未定义行为</span><br />
|
|
a<span class="br0">[</span>i<span class="br0">]</span> <span class="sy1">=</span> i<span class="sy2">++</span><span class="sy4">;</span> <span class="co1">// C++17 前为未定义行为</span><br />
|
|
n <span class="sy1">=</span> <span class="sy2">++</span>i <span class="sy2">+</span> i<span class="sy4">;</span> <span class="co1">// 未定义行为</span></span></span></p>
|
|
<h2><span class="mw-headline" id=".E5.BA.8F.E5.88.97.E7.82.B9.E8.A7.84.E5.88.99_.28C.2B.2B11_.E5.89.8D.29">序列点规则 <span class="t-mark-rev t-until-cxx11">(C++11 前)</span></span></h2>
|
|
<h3><span class="mw-headline" id=".E5.AE.9A.E4.B9.89_2">定义</span></h3>
|
|
<p>表达式的求值可能产生副作用,包括:访问 <code>volatile</code> 左值所指代的对象,修改对象,调用库 I/O 函数,或任何做出这些操作的函数。</p>
|
|
<p><i>序列点 (sequence point)</i>是执行序列中的点,在该点所有来自序列中先前求值的副作用均已完成,而后继求值的副作用都未开始。</p>
|
|
<h3><span class="mw-headline" id=".E8.A7.84.E5.88.99_2">规则</span></h3>
|
|
<p>1) 每个全表达式结尾(典型地在分号处)有一个序列点。</p>
|
|
<p>2) 调用函数时(无论该函数是否内联,无论是否使用函数调用语法),所有函数实参的求值(若存在)之后有一个序列点,它发生于函数体内的任何表达式或语句的执行之前。</p>
|
|
<p>3) 对函数的返回值进行复制之后,并在函数外任何表达式的执行之前有一个序列点。</p>
|
|
<p>4) 一旦函数执行开始,则在被调用函数的执行完成前,不求值调用方函数的任何表达式(函数不能交错执行)。</p>
|
|
<p>5) 每个使用内建(非重载)运算符的下列四种表达式的求值中,表达式 <code>a</code> 的求值后有一个序列点。</p>
|
|
<p><span class="t-c"><span class="mw-geshi cpp source-cpp">a <span class="sy3">&&</span> b<br />
|
|
a <span class="sy3">||</span> b<br />
|
|
a <span class="sy4">?</span> b <span class="sy4">:</span> c<br />
|
|
a , b</span></span></p>
|
|
<h3><span class="mw-headline" id=".E6.9C.AA.E5.AE.9A.E4.B9.89.E8.A1.8C.E4.B8.BA_2">未定义行为</span></h3>
|
|
<p>1) 前后序列点间,至多可以修改标量对象的存储值一次,否则<a href="cpp-language-ub.html">其行为未定义</a>。</p>
|
|
<p><span class="t-c"><span class="mw-geshi cpp source-cpp">i <span class="sy1">=</span> <span class="sy2">++</span>i <span class="sy2">+</span> i<span class="sy2">++</span><span class="sy4">;</span> <span class="co1">// 未定义行为</span><br />
|
|
i <span class="sy1">=</span> i<span class="sy2">++</span> <span class="sy2">+</span> <span class="nu0">1</span><span class="sy4">;</span> <span class="co1">// 未定义行为( C++17 前)</span><br />
|
|
i <span class="sy1">=</span> <span class="sy2">++</span>i <span class="sy2">+</span> <span class="nu0">1</span><span class="sy4">;</span> <span class="co1">// 未定义行为( C++11 前)</span><br />
|
|
<span class="sy2">++</span> <span class="sy2">++</span>i<span class="sy4">;</span> <span class="co1">// 未定义行为( C++11 前)</span><br />
|
|
f<span class="br0">(</span><span class="sy2">++</span>i, <span class="sy2">++</span>i<span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 未定义行为( C++17 前)</span><br />
|
|
f<span class="br0">(</span>i <span class="sy1">=</span> <span class="sy2">-</span><span class="nu0">1</span>, i <span class="sy1">=</span> <span class="sy2">-</span><span class="nu0">1</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 未定义行为( C++17 前)</span></span></span></p>
|
|
<p>2) 前后序列点间,访问表达式求值所修改的标量对象的先前值,必须只为确定要存储的值。若以任何其他方式访问,则<a href="cpp-language-ub.html">其行为未定义</a>。</p>
|
|
<p><span class="t-c"><span class="mw-geshi cpp source-cpp">cout <span class="sy1"><<</span> i <span class="sy1"><<</span> i<span class="sy2">++</span><span class="sy4">;</span> <span class="co1">// 未定义行为( C++17 前)</span><br />
|
|
a<span class="br0">[</span>i<span class="br0">]</span> <span class="sy1">=</span> i<span class="sy2">++</span><span class="sy4">;</span> <span class="co1">// 未定义行为( C++17 前)</span></span></span></p>
|
|
<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/issue1885">CWG 1885</a></td>
|
|
<td>C++14</td>
|
|
<td>函数返回时自动变量的销毁顺序不明确</td>
|
|
<td>添加顺序规则</td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E5.BC.95.E7.94.A8">引用</span></h3>
|
|
<div class="t-ref-std-c++11">
|
|
<ul>
|
|
<li>C++11 标准(ISO/IEC 14882:2011):</li>
|
|
</ul>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>1.9 Program execution [intro.execution]</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>5.2.6 Increment and decrement [expr.post.incr]</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>5.3.4 New [expr.new]</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>5.14 Logical AND operator [expr.log.and]</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>5.15 Logical OR operator [expr.log.or]</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>5.16 Conditional operator [expr.cond]</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>5.17 Assignment and compound assignment operators [expr.ass]</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>5.18 Comma operator [expr.comma]</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>8.5.4 List-initialization [dcl.init.list]</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E5.8F.82.E9.98.85">参阅</span></h3>
|
|
<ul>
|
|
<li><a href="cpp-language-operator_precedence.html">运算符优先级</a>,定义从表达式的源码表示构建它的方式。</li>
|
|
</ul>
|
|
<table class="t-dsc-begin"></table>
|
|
</div>
|
|
<div class="visualClear"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|