上传cppreference
This commit is contained in:
342
web/cppreference-zh/chmhelp/cpp-language-noexcept_spec.html
Normal file
342
web/cppreference-zh/chmhelp/cpp-language-noexcept_spec.html
Normal file
@@ -0,0 +1,342 @@
|
||||
<!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>noexcept 说明符 (C++11 起)</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_noexcept_spec skin-cppreference2 action-view cpp-navbar">
|
||||
<div id="cpp-content-base">
|
||||
<div id="content"><a id="top"></a>
|
||||
<h1 id="firstHeading" class="firstHeading">noexcept 说明符 <span class="t-mark-rev t-since-cxx11">(C++11 起)</span></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><code><b>noexcept</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><code><b>noexcept(</b></code><span class="t-spar">表达式</span><code><b>)</b></code></td>
|
||||
<td>(2)</td>
|
||||
<td class="t-sdsc-nopad"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="10" class="t-sdsc-sep"></td>
|
||||
</tr>
|
||||
<tr class="t-sdsc">
|
||||
<td><code><b>throw()</b></code></td>
|
||||
<td>(3)</td>
|
||||
<td><span class="t-mark-rev t-since-cxx17">(C++17 起)</span><br />
|
||||
<span class="t-mark-rev t-deprecated-cxx17">(C++17 中弃用)</span><br />
|
||||
<span class="t-mark-rev t-until-cxx20">(C++20 中移除)</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="10" class="t-sdsc-sep"></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="t-li1"><span class="t-li">1)</span> 与 <code><b>noexcept(true)</b></code> 相同</div>
|
||||
<div class="t-li1"><span class="t-li">2)</span> 如果 <span class="t-spar">表达式</span> 求值为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw2">true</span></span></span>,那么声明函数不会抛出任何异常。</div>
|
||||
<div class="t-li1"><span class="t-li">3)</span> 与 <code><b>noexcept(true)</b></code> 相同(C++17 前的语义见<a href="cpp-language-except_spec.html">动态异常说明</a>)</div>
|
||||
<table class="t-par-begin">
|
||||
<tr class="t-par">
|
||||
<td><span class="t-spar">表达式</span></td>
|
||||
<td>-</td>
|
||||
<td><a href="cpp-language-constant_expression.html#.E7.BB.8F.E8.BD.AC.E6.8D.A2.E7.9A.84.E5.B8.B8.E9.87.8F.E8.A1.A8.E8.BE.BE.E5.BC.8F">按语境转换为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">bool</span></span></span> 类型的常量表达式</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3><span class="mw-headline" id=".E8.A7.A3.E9.87.8A">解释</span></h3>
|
||||
<table class="t-rev-begin">
|
||||
<tr class="t-rev t-until-cxx17">
|
||||
<td>
|
||||
<p>noexcept 说明不是函数类型的一部分(正如同<a href="cpp-language-except_spec.html">动态异常说明</a>),而且只能在声明函数、变量、函数类型的非静态数据成员、函数指针、函数引用或成员函数指针时,以及在以上这些声明中声明类型为函数指针或函数引用的形参或返回类型时,作为 <a href="cpp-language-lambda.html">lambda 声明符</a>或顶层<a href="cpp-language-function.html">函数声明符</a>的一部分出现。它不能在 <a href="cpp-language-typedef.html">typedef</a> 或<a href="cpp-language-type_alias.html">类型别名</a>声明中出现。</p>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="kw4">void</span> f<span class="br0">(</span><span class="br0">)</span> <span class="kw1">noexcept</span><span class="sy4">;</span> <span class="co1">// 函数 f() 不会抛出</span>
|
||||
<span class="kw4">void</span> <span class="br0">(</span><span class="sy2">*</span>fp<span class="br0">)</span><span class="br0">(</span><span class="br0">)</span> <span class="kw1">noexcept</span><span class="br0">(</span><span class="kw2">false</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// fp 指向可能会抛出的函数</span>
|
||||
<span class="kw4">void</span> g<span class="br0">(</span><span class="kw4">void</span> pfa<span class="br0">(</span><span class="br0">)</span> <span class="kw1">noexcept</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// g 接收指向不会抛出的函数的指针</span>
|
||||
<span class="co1">// typedef int (*pf)() noexcept; // 错误</span></pre></div>
|
||||
</div>
|
||||
</td>
|
||||
<td><span class="t-mark-rev t-until-cxx17">(C++17 前)</span></td>
|
||||
</tr>
|
||||
<tr class="t-rev t-since-cxx17">
|
||||
<td>
|
||||
<p>noexcept 说明是函数类型的一部分,可以作为任何<a href="cpp-language-function.html">函数声明符</a>的一部分出现。</p>
|
||||
</td>
|
||||
<td><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>C++ 中的每个函数要么<i>不会抛出</i>,要么<i>有可能会抛出</i>。</p>
|
||||
<ul>
|
||||
<li><i>有可能会抛出</i>的函数是:</li>
|
||||
</ul>
|
||||
<table class="t-rev-begin">
|
||||
<tr class="t-rev t-until-cxx17">
|
||||
<td>
|
||||
<dl>
|
||||
<dd>
|
||||
<ul>
|
||||
<li>声明带有非空<a href="cpp-language-except_spec.html">动态异常说明</a>的函数。</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</td>
|
||||
<td><span class="t-mark-rev t-until-cxx17">(C++17 前)</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
<dl>
|
||||
<dd>
|
||||
<ul>
|
||||
<li>声明带有求值为 <code>false</code> 的 <span class="t-spar">表达式</span> 的 <code>noexcept</code> 说明符的函数</li>
|
||||
<li>声明不带有 <code>noexcept</code> 声明的函数,除了</li>
|
||||
</ul>
|
||||
<dl>
|
||||
<dd>
|
||||
<ul>
|
||||
<li><a href="cpp-language-destructor.html">析构函数</a>,除非有任何可能在构造的基类或成员的析构函数<i>有可能会抛出</i>(见下文)</li>
|
||||
<li>隐式声明的或在它的首个声明被预置的<a href="cpp-language-default_constructor.html">默认构造函数</a>、<a href="cpp-language-copy_constructor.html">复制构造函数</a>、<a href="cpp-language-move_constructor.html">移动构造函数</a>,除非</li>
|
||||
</ul>
|
||||
<dl>
|
||||
<dd>
|
||||
<ul>
|
||||
<li>由构造函数的隐式定义所调用的某个基类或成员的构造函数<i>有可能会抛出</i>(见下文)</li>
|
||||
<li>这种初始化的某个子表达式,例如默认实参表达式,<i>有可能会抛出</i>(见下文)</li>
|
||||
<li>(默认构造函数的)默认成员初始化器<i>有可能会抛出</i>(见下文)</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
<ul>
|
||||
<li>隐式声明的或在它的首个声明被预置的<a href="cpp-language-copy_assignment.html">复制赋值</a>运算符、<a href="cpp-language-move_assignment.html">移动赋值</a>运算符,除非隐式定义中对任何赋值运算符的调用<i>有可能会抛出</i>(见下文)</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
<table class="t-rev-begin">
|
||||
<tr class="t-rev t-since-cxx20">
|
||||
<td>
|
||||
<dl>
|
||||
<dd>
|
||||
<dl>
|
||||
<dd>
|
||||
<ul>
|
||||
<li>在它的首个声明被预置的<a href="cpp-language-default_comparisons.html">比较运算符</a>,除非它的隐式定义中对任何比较运算符的调用<i>有可能会抛出</i>(见下文)</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</td>
|
||||
<td><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
<dl>
|
||||
<dd>
|
||||
<dl>
|
||||
<dd>
|
||||
<ul>
|
||||
<li><a href="cpp-memory-new-operator_delete.html">解分配函数</a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
<ul>
|
||||
<li>所有其他函数(以求值为 <code>true</code> 的 <span class="t-spar">表达式</span> 的 <code>noexcept</code> 说明符声明的函数,以及析构函数、预置的特殊成员函数和解分配函数)都<i>不会抛出</i></li>
|
||||
</ul>
|
||||
<p><a href="cpp-language-function_template.html#.E6.98.BE.E5.BC.8F.E5.AE.9E.E4.BE.8B.E5.8C.96">显式实例化</a>可以使用 <code>noexcept</code> 说明符,但不要求。如果有使用,那么它的异常说明必须与所有其他声明相同。只有在这些异常说明在同一翻译单元中不相同时才要求诊断。</p>
|
||||
<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>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="kw4">void</span> f<span class="br0">(</span><span class="br0">)</span> <span class="kw1">noexcept</span><span class="sy4">;</span>
|
||||
<span class="kw4">void</span> f<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 错误:异常说明不同</span>
|
||||
<span class="kw4">void</span> g<span class="br0">(</span><span class="br0">)</span> <span class="kw1">noexcept</span><span class="br0">(</span><span class="kw2">false</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="sy4">;</span> <span class="co1">// OK:g 的两个声明均有可能会抛出</span></pre></div>
|
||||
</div>
|
||||
<p>指向不会抛出的函数的指针(包括成员函数指针)<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><a href="cpp-language-implicit_conversion.html#.E5.87.BD.E6.95.B0.E6.8C.87.E9.92.88.E8.BD.AC.E6.8D.A2">可以隐式转换到</a></span> <span><span class="t-mark-rev t-since-cxx17">(C++17 起)</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">void</span> ft<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 有可能会抛出</span>
|
||||
<span class="kw4">void</span> <span class="br0">(</span><span class="sy2">*</span>fn<span class="br0">)</span><span class="br0">(</span><span class="br0">)</span> <span class="kw1">noexcept</span> <span class="sy1">=</span> ft<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> B <span class="br0">{</span>
|
||||
<span class="kw1">virtual</span> <span class="kw4">void</span> f<span class="br0">(</span><span class="br0">)</span> <span class="kw1">noexcept</span><span class="sy4">;</span>
|
||||
<span class="kw1">virtual</span> <span class="kw4">void</span> g<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span>
|
||||
<span class="kw1">virtual</span> <span class="kw4">void</span> h<span class="br0">(</span><span class="br0">)</span> <span class="kw1">noexcept</span> <span class="sy1">=</span> delete<span class="sy4">;</span>
|
||||
<span class="br0">}</span><span class="sy4">;</span>
|
||||
|
||||
<span class="kw1">struct</span> D<span class="sy4">:</span> B <span class="br0">{</span>
|
||||
<span class="kw4">void</span> f<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 谬构:D::f 有可能会抛出,B::f 不会抛出</span>
|
||||
<span class="kw4">void</span> g<span class="br0">(</span><span class="br0">)</span> <span class="kw1">noexcept</span><span class="sy4">;</span> <span class="co1">// OK</span>
|
||||
<span class="kw4">void</span> h<span class="br0">(</span><span class="br0">)</span> <span class="sy1">=</span> delete<span class="sy4">;</span> <span class="co1">// OK</span>
|
||||
<span class="br0">}</span><span class="sy4">;</span></pre></div>
|
||||
</div>
|
||||
<p>不会抛出的函数允许调用有可能会抛出的函数。每当抛出异常且对处理块的查找遇到了不会抛出的函数的最外层块时,就调用函数 <span class="t-lc"><a href="cpp-error-terminate.html">std::terminate</a></span> <span class="t-rev-inl t-until-cxx17"><span>或 <span class="t-lc"><a href="cpp-error-unexpected.html">std::unexpected</a></span></span> <span><span class="t-mark-rev t-until-cxx17">(C++17 前)</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">extern</span> <span class="kw4">void</span> f<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 有可能会抛出</span>
|
||||
|
||||
<span class="kw4">void</span> g<span class="br0">(</span><span class="br0">)</span> <span class="kw1">noexcept</span> <span class="br0">{</span>
|
||||
f<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 合法,即使 f 抛出</span>
|
||||
<span class="kw1">throw</span> <span class="nu0">42</span><span class="sy4">;</span> <span class="co1">// 合法,等效于调用 std::terminate</span>
|
||||
<span class="br0">}</span></pre></div>
|
||||
</div>
|
||||
<table class="t-rev-begin">
|
||||
<tr class="t-rev t-since-cxx14">
|
||||
<td>
|
||||
<p>函数模板特化的异常说明不随函数声明而实例化;它只会在<i>需要</i>(定义如下)时实例化。</p>
|
||||
<p>隐式声明的特殊成员函数的异常说明也只会在需要时求值(特别是,派生类成员函数的隐式声明不要求实例化基类成员函数的异常说明)</p>
|
||||
<p>在<i>需要</i>但尚未实例化某个函数模板特化的 noexcept 说明时,如同对该特化的声明一样,对待决名进行查找并实例化 <span class="t-spar">表达式</span> 中用到的任何模板。</p>
|
||||
<p>在下列语境中认为<i>需要</i>函数的 noexcept 说明:</p>
|
||||
<ul>
|
||||
<li>在表达式中,函数被重载决议选中</li>
|
||||
<li>函数被<a href="cpp-language-definition.html#ODR_.E4.BD.BF.E7.94.A8">ODR 使用</a></li>
|
||||
<li>函数本该被 ODR 使用但在不求值操作数中出现:</li>
|
||||
</ul>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="kw1">template</span><span class="sy1"><</span><span class="kw1">class</span> T<span class="sy1">></span> T f<span class="br0">(</span><span class="br0">)</span> <span class="kw1">noexcept</span><span class="br0">(</span>sizeof<span class="br0">(</span>T<span class="br0">)</span> <span class="sy1"><</span> <span class="nu0">4</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>
|
||||
decltype<span class="br0">(</span>f<span class="sy1"><</span><span class="kw4">void</span><span class="sy1">></span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span> <span class="sy2">*</span>p<span class="sy4">;</span> <span class="co1">// f 不求值,但需要 noexcept 说明</span>
|
||||
<span class="co1">// 错误,因为实例化 noexcept 说明的实例化要计算 sizeof(void)</span>
|
||||
<span class="br0">}</span></pre></div>
|
||||
</div>
|
||||
<ul>
|
||||
<li>该特化需要与另一函数声明进行比较(例如在虚函数覆盖或函数模板的显式特化处)</li>
|
||||
<li>在函数定义中</li>
|
||||
<li>需要异常说明,因为某个预置特殊成员函数需要检查它以决定它自身的异常说明(这只会在这个预置特殊成员函数自身的异常说明被需要时发生)。</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td><span class="t-mark-rev t-since-cxx14">(C++14 起)</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p><br />
|
||||
<i>有可能会抛出的表达式</i>的正式定义(用于确定上述析构函数、构造函数和赋值运算符的默认异常说明)是:</p>
|
||||
<p>以下情况下,表达式 <code>e</code> <i>有可能会抛出</i>:</p>
|
||||
<ul>
|
||||
<li><code>e</code> 是对<i>有可能会抛出</i>的函数、函数指针或成员函数指针的调用<span class="t-rev-inl t-until-cxx17"><span>,除非 <code>e</code> 是<a href="cpp-language-constant_expression.html">核心常量表达式</a></span> <span><span class="t-mark-rev t-until-cxx17">(C++17 前)</span></span></span></li>
|
||||
<li><code>e</code> 对<i>有可能会抛出</i>的函数进行隐式调用(例如作为重载运算符,new 表达式中的分配函数,函数实参的构造函数,或当 <code>e</code> 为完整表达式时的析构函数)</li>
|
||||
<li><code>e</code> 是 <a href="cpp-language-throw.html">throw 表达式</a></li>
|
||||
<li><code>e</code> 是对多态引用类型进行转型的 <a href="cpp-language-dynamic_cast.html"><code>dynamic_cast</code></a></li>
|
||||
<li><code>e</code> 是应用于指向多态类型的指针的解引用的 <a href="cpp-language-typeid.html"><code>typeid</code></a> 表达式</li>
|
||||
<li><code>e</code> 包含<i>有可能会抛出</i>的直接子表达式</li>
|
||||
</ul>
|
||||
<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>
|
||||
A<span class="br0">(</span><span class="kw4">int</span> <span class="sy1">=</span> <span class="br0">(</span>A<span class="br0">(</span><span class="nu0">5</span><span class="br0">)</span>, <span class="nu0">0</span><span class="br0">)</span><span class="br0">)</span> <span class="kw1">noexcept</span><span class="sy4">;</span>
|
||||
A<span class="br0">(</span><span class="kw4">const</span> A<span class="sy3">&</span><span class="br0">)</span> <span class="kw1">noexcept</span><span class="sy4">;</span>
|
||||
A<span class="br0">(</span>A<span class="sy3">&&</span><span class="br0">)</span> <span class="kw1">noexcept</span><span class="sy4">;</span>
|
||||
~A<span class="br0">(</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>
|
||||
B<span class="br0">(</span><span class="br0">)</span> <span class="kw1">throw</span><span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span>
|
||||
B<span class="br0">(</span><span class="kw4">const</span> B<span class="sy3">&</span><span class="br0">)</span> <span class="sy1">=</span> <span class="kw1">default</span><span class="sy4">;</span> <span class="co1">// 隐式异常说明是 noexcept(true)</span>
|
||||
B<span class="br0">(</span>B<span class="sy3">&&</span>, <span class="kw4">int</span> <span class="sy1">=</span> <span class="br0">(</span><span class="kw1">throw</span> Y<span class="br0">(</span><span class="br0">)</span>, <span class="nu0">0</span><span class="br0">)</span><span class="br0">)</span> <span class="kw1">noexcept</span><span class="sy4">;</span>
|
||||
~B<span class="br0">(</span><span class="br0">)</span> <span class="kw1">noexcept</span><span class="br0">(</span><span class="kw2">false</span><span class="br0">)</span><span class="sy4">;</span>
|
||||
<span class="br0">}</span><span class="sy4">;</span>
|
||||
|
||||
<span class="kw4">int</span> n <span class="sy1">=</span> <span class="nu0">7</span><span class="sy4">;</span>
|
||||
<span class="kw1">struct</span> D <span class="sy4">:</span> <span class="kw1">public</span> A, <span class="kw1">public</span> B <span class="br0">{</span>
|
||||
<span class="kw4">int</span> <span class="sy2">*</span> p <span class="sy1">=</span> new <span class="kw4">int</span><span class="br0">[</span>n<span class="br0">]</span><span class="sy4">;</span>
|
||||
<span class="co1">// D::D() 有可能会抛出,因为 new 运算符</span>
|
||||
<span class="co1">// D::D(const D&) 不会抛出</span>
|
||||
<span class="co1">// D::D(D&&) 有可能会抛出:因为 B 的构造函数的默认实参有可能会抛出</span>
|
||||
<span class="co1">// D::~D() 有可能会抛出</span>
|
||||
|
||||
<span class="co1">// 注意:如果 A::~A() 为虚,那么此程序将为非良构,因为不会抛出的虚函数的覆盖函数不能抛出</span>
|
||||
<span class="br0">}</span><span class="sy4">;</span></pre></div>
|
||||
</div>
|
||||
<h3><span class="mw-headline" id=".E6.B3.A8.E8.A7.A3">注解</span></h3>
|
||||
<p>常量 <span class="t-spar">表达式</span> 的一种用法(与 <a href="cpp-language-noexcept.html"><code>noexcept</code> 运算符</a>一起)是,定义函数模板,它对一些类型声明 <code><b>noexcept</b></code>,但对其他类型不声明。</p>
|
||||
<p>注意,函数上的 <code><b>noexcept</b></code> 说明不是一种编译时检查;它只不过是程序员告知编译器函数是否可以抛出异常的一种方法。编译器能用此信息启用不会抛出的函数上的某些优化,以及启用能在编译时检查特定表达式是否声明为可抛出任何异常的 <a href="cpp-language-noexcept.html"><code>noexcept</code> 运算符</a>。例如,诸如 <span class="t-lc"><a href="cpp-container-vector.html">std::vector</a></span> 的容器会在元素的移动构造函数是 <code><b>noexcept</b></code> 的情况下移动元素,否则就复制元素(除非复制构造函数不可访问,但有可能会抛出的移动构造函数只会在放弃强异常保证的情况下考虑)。</p>
|
||||
<h4><span class="mw-headline" id=".E5.BC.83.E7.94.A8">弃用</span></h4>
|
||||
<p><code><b>noexcept</b></code> 是 <a href="cpp-language-except_spec.html"><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw1">throw</span><span class="br0">(</span><span class="br0">)</span></span></span></a> 的改进版本,后者在 C++11 中弃用。与 C++17 前的 <a href="cpp-language-except_spec.html"><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw1">throw</span><span class="br0">(</span><span class="br0">)</span></span></span></a> 不同,<code><b>noexcept</b></code> 不会调用 <span class="t-lc"><a href="cpp-error-unexpected.html">std::unexpected</a></span>,并且可能或可能不进行栈回溯,这可能允许编译器实现没有 <a href="cpp-language-except_spec.html"><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw1">throw</span><span class="br0">(</span><span class="br0">)</span></span></span></a> 的运行时开销的 <code><b>noexcept</b></code>。从 C++17 起,<span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw1">throw</span><span class="br0">(</span><span class="br0">)</span></span></span> 被重定义为严格等价于 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw1">noexcept</span><span class="br0">(</span><span class="kw2">true</span><span class="br0">)</span></span></span>。</p>
|
||||
<h3><span class="mw-headline" id=".E5.85.B3.E9.94.AE.E8.AF.8D">关键词</span></h3>
|
||||
<p><a href="cpp-keyword-noexcept.html"><tt>noexcept</tt></a></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="co1">// foo 是否声明为 noexcept 取决于 T() 是否会抛出异常</span>
|
||||
<span class="kw1">template</span> <span class="sy1"><</span><span class="kw1">class</span> T<span class="sy1">></span>
|
||||
<span class="kw4">void</span> foo<span class="br0">(</span><span class="br0">)</span> <span class="kw1">noexcept</span><span class="br0">(</span><span class="kw1">noexcept</span><span class="br0">(</span>T<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span><span class="br0">}</span>
|
||||
|
||||
<span class="kw4">void</span> bar<span class="br0">(</span><span class="br0">)</span> <span class="kw1">noexcept</span><span class="br0">(</span><span class="kw2">true</span><span class="br0">)</span> <span class="br0">{</span><span class="br0">}</span>
|
||||
<span class="kw4">void</span> baz<span class="br0">(</span><span class="br0">)</span> <span class="kw1">noexcept</span> <span class="br0">{</span> <span class="kw1">throw</span> <span class="nu0">42</span><span class="sy4">;</span> <span class="br0">}</span> <span class="co1">// noexcept 等同于 noexcept(true)</span>
|
||||
|
||||
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span>
|
||||
<span class="br0">{</span>
|
||||
foo<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span><span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// noexcept(noexcept(int())) => noexcept(true),所以这是可以的</span>
|
||||
|
||||
bar<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 可以</span>
|
||||
baz<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 能编译,但会在运行时调用 std::terminate</span>
|
||||
<span class="br0">}</span></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/issue2039">CWG 2039</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>
|
||||
<table class="t-dsc-begin">
|
||||
<tr class="t-dsc">
|
||||
<td><a href="cpp-language-noexcept.html"><code>noexcept</code> 运算符</a><span class="t-mark-rev t-since-cxx11">(C++11)</span></td>
|
||||
<td>确定表达式是否会抛出任何异常</td>
|
||||
</tr>
|
||||
<tr class="t-dsc">
|
||||
<td><a href="cpp-language-except_spec.html">动态异常说明</a><span class="t-mark-rev t-until-cxx17">(C++17 前)</span></td>
|
||||
<td>指定函数所抛出的异常 <span class="t-mark-rev t-deprecated-cxx11">(C++11 中弃用)</span></td>
|
||||
</tr>
|
||||
<tr class="t-dsc">
|
||||
<td><a href="cpp-language-throw.html">throw 表达式</a></td>
|
||||
<td>引发错误并将控制转移到错误处理块</td>
|
||||
</tr>
|
||||
<tr class="t-dsc">
|
||||
<td>
|
||||
<div class="t-dsc-member-div">
|
||||
<div><a href="cpp-utility-move_if_noexcept.html"><span class="t-lines"><span>move_if_noexcept</span></span></a></div>
|
||||
<div><span class="t-lines"><span><span class="t-mark-rev t-since-cxx11">(C++11)</span></span></span></div>
|
||||
</div>
|
||||
</td>
|
||||
<td>若移动构造函数不抛出则获得右值引用<br />
|
||||
<span class="t-mark">(函数模板)</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="visualClear"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user