217 lines
22 KiB
HTML
217 lines
22 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>属性说明符序列(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_attributes skin-cppreference2 action-view cpp-navbar">
|
|
<div id="cpp-content-base">
|
|
<div id="content"><a id="top"></a>
|
|
<h1 id="firstHeading" class="firstHeading">属性说明符序列<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>
|
|
<dl>
|
|
<dd><code><b>[[</b></code><span class="t-spar">属性</span><code><b>]]</b></code> <code><b>[[</b></code><span class="t-spar">属性1</span>, <span class="t-spar">属性2</span>, <span class="t-spar">属性3</span><code><b>(</b></code><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">属性</span><code><b>(</b></code><span class="t-spar">实参</span><code><b>)</b></code><code><b>]]</b></code> <span class="t-spar">alignas-说明符</span></dd>
|
|
</dl>
|
|
<p>正式而言,语法是</p>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><code><b>[[</b></code> <span class="t-spar">属性列表</span> <code><b>]]</b></code></td>
|
|
<td class="t-sdsc-nopad"></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><code><b>[[</b></code> <code><b>using</b></code> <span class="t-spar">属性命名空间</span> <code><b>:</b></code> <span class="t-spar">属性列表</span> <code><b>]]</b></code></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<p>其中 <span class="t-spar">属性列表</span> 是由逗号分隔的零或更多个 <span class="t-spar">属性</span> 的序列(可以以指示<a href="cpp-language-parameter_pack.html">包展开</a>的省略号 <code><b>...</b></code> 结束)</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></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<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></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<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> <code><b>)</b></code></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td class="t-sdsc-nopad"><span class="t-spar">属性命名空间</span> <code><b>::</b></code> <span class="t-spar">标识符</span> <code><b>(</b></code> <span class="t-spar">实参列表</span> <code><b>)</b></code></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<div class="t-li1"><span class="t-li">1)</span> 简单属性,例如 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="br0">[</span><span class="br0">[</span>noreturn<span class="br0">]</span><span class="br0">]</span></span></span></div>
|
|
<div class="t-li1"><span class="t-li">2)</span> 有命名空间的属性,例如 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="br0">[</span><span class="br0">[</span>gnu<span class="sy4">::</span><span class="me2">unused</span><span class="br0">]</span><span class="br0">]</span></span></span></div>
|
|
<div class="t-li1"><span class="t-li">3)</span> 有实参的属性,例如 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="br0">[</span><span class="br0">[</span>deprecated<span class="br0">(</span><span class="st0">"because"</span><span class="br0">)</span><span class="br0">]</span><span class="br0">]</span></span></span></div>
|
|
<div class="t-li1"><span class="t-li">4)</span> 既有命名空间又有实参列表的属性</div>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx17">
|
|
<td>
|
|
<p>若 <code>using: namespace</code> 出现在属性列表开端,则属性列表中的其他属性均不得指定命名空间:由 using 所指定的命名空间会应用到所有这些属性:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="br0">[</span><span class="br0">[</span><span class="kw1">using</span> CC<span class="sy4">:</span> opt<span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span>, debug<span class="br0">]</span><span class="br0">]</span> <span class="co1">// 同 [[CC::opt(1), CC::debug]]</span>
|
|
<span class="br0">[</span><span class="br0">[</span><span class="kw1">using</span> CC<span class="sy4">:</span> CC<span class="sy4">::</span><span class="me2">opt</span><span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span><span class="br0">]</span><span class="br0">]</span> <span class="co1">// 错误:不能结合 using 和有作用域属性</span></pre></div>
|
|
</div>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E8.A7.A3.E9.87.8A">解释</span></h3>
|
|
<p>属性为各种由实现定义的语言扩展(例如 GNU 与 IBM 的语言扩展 <code>__attribute__((...))</code>,微软的语言扩展 <code>__declspec()</code> 等)提供了统一化的语法。</p>
|
|
<p>属性可用在 C++ 程序中的几乎所有位置,而且可应用于几乎所有事物:类型、变量、函数、名字、代码块、整个翻译单元,不过每个特定的属性都只在实现允许范围内有效:<code>[[expect_true]]</code> 可能是只能与 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw1">if</span></span></span>,而非与类声明一同使用的属性,<code>[[omp::parallel()]]</code> 可能是应用到代码块或 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw1">for</span></span></span> 循环,而非到类型 <code>int</code> 等的属性。(请注意以上两个属性只是虚构的例子,有关标准与一些非标准属性请见下文)</p>
|
|
<p>在声明中,属性既可以出现在整个声明之前,也可以直接跟在被声明实体的名字之后,这些情况下它们被组合起来。大多数其他情形中,属性应用于直接位于其之前的实体。</p>
|
|
<p>虽然 <a href="cpp-language-alignas.html"><code>alignas</code> 说明符</a>拥有不同的语法,但它是属性序列说明符的一部分。它可以出现于 <code>[[...]]</code> 属性出现处,并可与它们混合(假设此处允许使用 <span class="t-c"><span class="mw-geshi cpp source-cpp">alignas</span></span>)</p>
|
|
<p>两个连续的方括号记号(<code>[[</code>)只能出现于引入属性说明符之处,或在属性实参之内。</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="br0">{</span>
|
|
<span class="kw4">int</span> y<span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span><span class="sy4">;</span>
|
|
y<span class="br0">[</span><span class="br0">[</span><span class="br0">]</span> <span class="br0">{</span> <span class="kw1">return</span> <span class="nu0">0</span><span class="sy4">;</span> <span class="br0">}</span><span class="br0">(</span><span class="br0">)</span><span class="br0">]</span> <span class="sy1">=</span> <span class="nu0">1</span><span class="sy4">;</span> <span class="co1">// 错误</span>
|
|
<span class="kw4">int</span> i <span class="br0">[</span><span class="br0">[</span>cats<span class="sy4">::</span><span class="me2">meow</span><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="br0">]</span><span class="br0">]</span><span class="sy4">;</span> <span class="co1">// OK</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<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>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx20">
|
|
<td>
|
|
<p>无 <span class="t-spar">属性命名空间</span> 的属性与名字以 <code>std</code> 或 <code>std</code> 后随一或多个数字的 <span class="t-spar">属性命名空间</span> 为未来标准化保留。即每个非标准属性都在实现提供的 <span class="t-spar">属性命名空间</span> 中,例如 <code>[[gnu::may_alias]]</code>、 <code>[[clang::trivial_abi]]</code> 和 <code>[[msvc::noop_dtor]]</code>。</p>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E6.A0.87.E5.87.86.E5.B1.9E.E6.80.A7">标准属性</span></h3>
|
|
<p>C++ 标准仅定义下列属性。</p>
|
|
<table class="t-dsc-begin">
|
|
<tr class="t-dsc">
|
|
<td><code>[[<a href="cpp-language-attributes-noreturn.html">noreturn</a>]]</code><span class="t-mark-rev t-since-cxx11">(C++11)</span></td>
|
|
<td>指示函数不返回</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><code>[[<a href="cpp-language-attributes-carries_dependency.html">carries_dependency</a>]]</code><span class="t-mark-rev t-since-cxx11">(C++11)</span></td>
|
|
<td>指示释放消费 <span class="t-lc"><a href="cpp-atomic-memory_order.html">std::memory_order</a></span> 中的依赖链传入和传出该函数。</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><code>[[<a href="cpp-language-attributes-deprecated.html">deprecated</a>]]</code><span class="t-mark-rev t-since-cxx14">(C++14)</span><br />
|
|
<code>[[deprecated("原因")]]</code><span class="t-mark-rev t-since-cxx14">(C++14)</span></td>
|
|
<td>指示允许使用声明有此属性的名称或实体,但因 <span class="t-spar">原因</span> 而不鼓励使用。</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><code>[[<a href="cpp-language-attributes-fallthrough.html">fallthrough</a>]]</code><span class="t-mark-rev t-since-cxx17">(C++17)</span></td>
|
|
<td>指示从前一 case 标号直落是有意的,而在发生直落时给出警告的编译器不应该为此诊断。</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><code>[[<a href="cpp-language-attributes-nodiscard.html">nodiscard</a>]]</code><span class="t-mark-rev t-since-cxx17">(C++17)</span><br />
|
|
<code>[[nodiscard("原因")]]</code><span class="t-mark-rev t-since-cxx20">(C++20)</span></td>
|
|
<td>鼓励编译器在返回值被舍弃时发布警告。</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><code>[[<a href="cpp-language-attributes-maybe_unused.html">maybe_unused</a>]]</code><span class="t-mark-rev t-since-cxx17">(C++17)</span></td>
|
|
<td>压制编译器在未使用实体上的警告,若存在。</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><code>[[<a href="cpp-language-attributes-likely.html">likely</a>]]</code><span class="t-mark-rev t-since-cxx20">(C++20)</span><br />
|
|
<code>[[<a href="cpp-language-attributes-likely.html">unlikely</a>]]</code><span class="t-mark-rev t-since-cxx20">(C++20)</span></td>
|
|
<td>指示编译器应该针对通过某语句的执行路径比任何其他执行路径更可能或更不可能的情况进行优化。</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><code>[[<a href="cpp-language-attributes-no_unique_address.html">no_unique_address</a>]]</code><span class="t-mark-rev t-since-cxx20">(C++20)</span></td>
|
|
<td>指示非静态数据成员不需要拥有不同于其类的所有其他非静态数据成员的地址。</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td><code>[[<a href="cpp-language-attributes-optimize_for_synchronized.html">optimize_for_synchronized</a>]]</code><span class="t-mark-rev t-since-tm-ts t-mark-ts">(TM TS)</span></td>
|
|
<td>指示应该针对来自 <a href="cpp-language-transactional_memory.html">synchronized 语句</a>的调用来优化该函数定义</td>
|
|
</tr>
|
|
</table>
|
|
<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="br0">[</span><span class="br0">[</span>gnu<span class="sy4">::</span><span class="me2">always_inline</span><span class="br0">]</span><span class="br0">]</span> <span class="br0">[</span><span class="br0">[</span>gnu<span class="sy4">::</span><span class="me2">hot</span><span class="br0">]</span><span class="br0">]</span> <span class="br0">[</span><span class="br0">[</span>gnu<span class="sy4">::</span><span class="kw4">const</span><span class="br0">]</span><span class="br0">]</span> <span class="br0">[</span><span class="br0">[</span>nodiscard<span class="br0">]</span><span class="br0">]</span>
|
|
<span class="kw1">inline</span> <span class="kw4">int</span> f<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 声明 f 带四个属性</span>
|
|
|
|
<span class="br0">[</span><span class="br0">[</span>gnu<span class="sy4">::</span><span class="me2">always_inline</span>, gnu<span class="sy4">::</span><span class="kw4">const</span>, gnu<span class="sy4">::</span><span class="me2">hot</span>, nodiscard<span class="br0">]</span><span class="br0">]</span>
|
|
<span class="kw4">int</span> f<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 同上,但使用含有四个属性的单个属性说明符</span>
|
|
|
|
<span class="co1">// C++17:</span>
|
|
<span class="br0">[</span><span class="br0">[</span><span class="kw1">using</span> gnu <span class="sy4">:</span> <span class="kw4">const</span>, always_inline, hot<span class="br0">]</span><span class="br0">]</span> <span class="br0">[</span><span class="br0">[</span>nodiscard<span class="br0">]</span><span class="br0">]</span>
|
|
<span class="kw4">int</span> f<span class="br0">[</span><span class="br0">[</span>gnu<span class="sy4">::</span><span class="me2">always_inline</span><span class="br0">]</span><span class="br0">]</span><span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 属性可出现于多个说明符中</span>
|
|
|
|
<span class="kw4">int</span> f<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</span> <span class="nu0">0</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="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.link/P2156R1">P2156R1</a></td>
|
|
<td>C++11</td>
|
|
<td>每个标准属性在一个 <span class="t-spar">属性列表</span> 中最多只能出现一次</td>
|
|
<td>无限制次数</td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E5.A4.96.E9.83.A8.E9.93.BE.E6.8E.A5">外部链接</span></h3>
|
|
<ul>
|
|
<li><a rel="nofollow" class="external text" href="https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html#Attribute-Syntax">GCC 中的属性</a>
|
|
<ul>
|
|
<li>这些属性可用作 <code>[[gnu::...]]</code> ,见<a rel="nofollow" class="external text" href="https://stackoverflow.com/questions/54639524/which-gnu-attributes-have-c11-syntax#comment96071307_54639524">此处</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a rel="nofollow" class="external text" href="https://clang.llvm.org/docs/AttributeReference.html">Clang 中的属性</a></li>
|
|
</ul>
|
|
<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>
|