124 lines
25 KiB
HTML
124 lines
25 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_identifiers 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>是一个由数字,下划线,大小写拉丁字母和大多数 Unicode 字符组成的任意长度的序列。有效的标识符必须以一个非数字字符(拉丁字母,下划线或类为 <a rel="nofollow" class="external text" href="http://www.unicode.org/reports/tr44/">XID_Start</a> 的 Unicode 字符)开头,而在非开头位置可以有非数字字符、数字及类为 <a rel="nofollow" class="external text" href="http://www.unicode.org/reports/tr44/">XID_Continue</a> 的 Unicode 字符。标识符区分大小写(小写和大写字母是不同的),而且每一个字符都是起作用的。每个标识符都必须遵循<a rel="nofollow" class="external text" href="https://www.unicode.org/charts/normalization/">正规化形式 C</a>。</p>
|
|
<p>注意:大多数实现中对 Unicode 标识符的支持是受限的,比如 <a rel="nofollow" class="external text" href="https://gcc.gnu.org/wiki/FAQ#What_is_the_status_of_adding_the_UTF-8_support_for_identifier_names_in_GCC.3F">gcc (10 之前)</a>。</p>
|
|
<h3><span class="mw-headline" id=".E5.9C.A8.E5.A3.B0.E6.98.8E.E4.B8.AD">在声明中</span></h3>
|
|
<p>可以用标识符来<a href="cpp-language-declarations.html">命名</a>对象、引用、函数、枚举项、类型、类成员、命名空间、模板、模板特化、形参包、goto 标号,以及其他实体,但有以下例外:</p>
|
|
<ul>
|
|
<li><a href="cpp-keyword.html">关键词</a>标识符不能用于其他目的;
|
|
<ul>
|
|
<li>关键词只有在<span class="t-spar">属性记号</span>中可做他用。(例如 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="br0">[</span><span class="br0">[</span><span class="kw1">private</span><span class="br0">]</span><span class="br0">]</span></span></span> 是一个合法<a href="cpp-language-attributes.html">属性</a>)<span class="t-mark-rev t-since-cxx11">(C++11 起)</span></li>
|
|
</ul>
|
|
</li>
|
|
<li>作为特定运算符与标点符的<a href="cpp-language-operator_alternative.html">代用表示</a>不能用于其他目的;</li>
|
|
</ul>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx11">
|
|
<td>
|
|
<ul>
|
|
<li>拥有特殊含义的标识符(<span class="t-c"><span class="mw-geshi cpp source-cpp">final</span></span><span class="t-rev-inl t-since-cxx20"><span>,<span class="t-c"><span class="mw-geshi cpp source-cpp">import</span></span>,<span class="t-c"><span class="mw-geshi cpp source-cpp">module</span></span></span> <span><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></span></span>和<span class="t-c"><span class="mw-geshi cpp source-cpp">override</span></span>)在特定语境不作为常规标识符使用,而是表达它们的特定含义;
|
|
<ul>
|
|
<li>在没有特别指明的情况下,这些标识符在既能作为常规标识符也能表达特定含义的场合均被视为常规标识符。</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<ul>
|
|
<li>其中任何位置带有双下划线的标识符都是被保留的;</li>
|
|
<li>以一个下划线跟着一个大写字母开头的标识符是被保留的;</li>
|
|
<li>以一个下划线开头的标识符在全局命名空间中是被保留的。</li>
|
|
</ul>
|
|
<p>这里“被保留”的意思是,标准库的头文件可能 <code>#define</code> 或者声明这样的标识符以便其内部使用,编译器可能会预先定义这种非标准的标识符,而且名字重整算法可能会假定某些这样的标识符是没有被使用的。如果程序员使用了这样的标识符的话,其行为是未定义的。</p>
|
|
<p>此外,在一个翻译单元 <code>#define</code> 或 <code>#undef</code> 特定名字是未定义行为,详情请见<a href="cpp-preprocessor-replace.html">保留宏名</a>。</p>
|
|
<h4><span class="mw-headline" id=".E5.83.B5.E5.B0.B8.E6.A0.87.E8.AF.86.E7.AC.A6">僵尸标识符</span></h4>
|
|
<p>C++14 起,某些标识符被从 C++ 标准库移除。它们列于<a href="cpp-symbol_index-zombie_names.html">僵尸名列表</a>。</p>
|
|
<p>然而,这些标识符仍然在某些语境中为以前的标准化保留。可移植的代码中,被移除的成员函数名不可用做函数式宏的名字,而其他被移除的成员名不可用作对象式宏的名字。</p>
|
|
<h3><span class="mw-headline" id=".E5.9C.A8.E8.A1.A8.E8.BE.BE.E5.BC.8F.E4.B8.AD">在表达式中</span></h3>
|
|
<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-expressions.html">表达式</a>使用。仅由这个标识符组成的表达式的结果,是该标识符所命名的实体。若该标识符命名的是某个函数、变量<span class="t-rev-inl t-since-cxx20"><span>、<a href="cpp-language-template_parameters.html#.E9.9D.9E.E7.B1.BB.E5.9E.8B.E6.A8.A1.E6.9D.BF.E5.BD.A2.E5.8F.82">模板形参对象</a></span> <span><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></span></span>或数据成员,则表达式的<a href="cpp-language-value_category.html">值类别</a>为<i>左值</i>,否则为<i>纯右值</i>(例如<a href="cpp-language-enum.html">枚举项</a>是纯右值表达式<span class="t-rev-inl t-since-cxx20"><span>,概念的特化是 bool 纯右值</span> <span><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></span></span>)。该表达式的类型以下列方式确定:</p>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx11">
|
|
<td>
|
|
<ul>
|
|
<li>若该(无限定)标识符所命名的实体是局部实体,且在该标识符所出现的声明区之外命名它时将导致它被穿插其间的某个 <a href="cpp-language-lambda.html">lambda 表达式</a> 按复制俘获,则该表达式的类型是命名最内层的这种穿插其间的 lambda 表达式的闭包对象中为这种俘获所声明的非静态数据成员的<a href="cpp-language-operator_member_access.html">类成员访问表达式</a>的类型。</li>
|
|
</ul>
|
|
<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">float</span> x, <span class="sy3">&</span>r <span class="sy1">=</span> x<span class="sy4">;</span>
|
|
<span class="br0">[</span><span class="sy1">=</span><span class="br0">]</span> <span class="br0">{</span>
|
|
decltype<span class="br0">(</span>x<span class="br0">)</span> y1<span class="sy4">;</span> <span class="co1">// y1 拥有 float 类型</span>
|
|
decltype<span class="br0">(</span><span class="br0">(</span>x<span class="br0">)</span><span class="br0">)</span> y2 <span class="sy1">=</span> y1<span class="sy4">;</span> <span class="co1">// y2 拥有 float const& 类型</span>
|
|
<span class="co1">// 因为此 lambda 非 mutable 而 x 是左值</span>
|
|
decltype<span class="br0">(</span>r<span class="br0">)</span> r1 <span class="sy1">=</span> y1<span class="sy4">;</span> <span class="co1">// r1 拥有 float& 类型</span>
|
|
decltype<span class="br0">(</span><span class="br0">(</span>r<span class="br0">)</span><span class="br0">)</span> r2 <span class="sy1">=</span> y2<span class="sy4">;</span> <span class="co1">// r2 拥有 float const& 类型</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></td>
|
|
</tr>
|
|
<tr class="t-rev t-since-cxx20">
|
|
<td>
|
|
<ul>
|
|
<li>若所命名的实体是某个 <code>T</code> 类型模板形参的模板形参对象,则表达式的类型为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">const</span> T</span></span> 。</li>
|
|
</ul>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<ul>
|
|
<li>否则,表达式的类型与被命名的实体的类型相同。</li>
|
|
</ul>
|
|
<p>在非静态<a href="cpp-language-member_functions.html">成员函数</a>内,命名非静态成员的每个标识符 <span class="t-c"><span class="mw-geshi cpp source-cpp">member</span></span> 都隐式变换成一个类成员访问表达式 <span class="t-c"><span class="mw-geshi cpp source-cpp">this<span class="sy2">-</span><span class="sy1">></span>member</span></span> 。</p>
|
|
<h4><span class="mw-headline" id=".E6.97.A0.E9.99.90.E5.AE.9A.E7.9A.84.E6.A0.87.E8.AF.86.E7.AC.A6">无限定的标识符</span></h4>
|
|
<p>除了适当声明了的标识符之外,以下各项也可以以相同方式用在表达式中:</p>
|
|
<ul>
|
|
<li>函数写法的<a href="cpp-language-operators.html">重载运算符</a>名,比如 <span class="t-c"><span class="mw-geshi cpp source-cpp">operator<span class="sy2">+</span></span></span> 或 <span class="t-c"><span class="mw-geshi cpp source-cpp"><a href="cpp-memory-new-operator_new.html"><span class="kw687">operator new</span></a></span></span>;</li>
|
|
<li><a href="cpp-language-cast_operator.html">用户定义转换函数</a>的名字,比如 <span class="t-c"><span class="mw-geshi cpp source-cpp">operator <span class="kw4">bool</span></span></span>;</li>
|
|
<li><a href="cpp-language-user_literal.html">用户定义字面量运算符</a>的名字,比如 <span class="t-c"><span class="mw-geshi cpp source-cpp">operator <span class="st0">""</span> _km</span></span>;</li>
|
|
<li><a href="cpp-language-templates.html">模板</a>的名字后随其实参列表,比如 <span class="t-c"><span class="mw-geshi cpp source-cpp">MyTemplate<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span></span></span>;</li>
|
|
<li><span class="t-c"><span class="mw-geshi cpp source-cpp">~</span></span> 字符后随类名,比如 <span class="t-c"><span class="mw-geshi cpp source-cpp">~MyClass</span></span>;</li>
|
|
<li><span class="t-c"><span class="mw-geshi cpp source-cpp">~</span></span> 字符后随 <a href="cpp-language-decltype.html">decltype</a> 说明符,比如 <span class="t-c"><span class="mw-geshi cpp source-cpp">~decltype<span class="br0">(</span>str<span class="br0">)</span></span></span>。</li>
|
|
</ul>
|
|
<p>这些和标识符一起,被称作<i>无限定的标识表达式</i>。</p>
|
|
<h4><span class="mw-headline" id=".E6.9C.89.E9.99.90.E5.AE.9A.E7.9A.84.E6.A0.87.E8.AF.86.E7.AC.A6">有限定的标识符</span></h4>
|
|
<p><i>有限定的标识表达式</i>是在无限定的标识表达式前面带上作用域解析运算符 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="sy4">::</span></span></span>,以及可选地带上一系列以作用域解析运算符分隔的 <span class="t-rev-inl t-since-cxx11"><span>枚举、</span> <span><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></span></span>类或命名空间的名字<span class="t-rev-inl t-since-cxx11"><span>,或者 <span class="t-lc">decltype</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"><a href="cpp-string-basic_string-npos.html"><span class="kw1231">std::<span class="me2">string</span><span class="sy4">::</span><span class="me2">npos</span></span></a></span></span> 是命名在命名空间 <span class="t-c"><span class="mw-geshi cpp source-cpp">std</span></span> 内的类 <span class="t-c"><span class="mw-geshi cpp source-cpp">string</span></span> 中的静态成员 <span class="t-c"><span class="mw-geshi cpp source-cpp">npos</span></span> 的表达式。表达式 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="sy4">::</span><span class="me2">tolower</span></span></span> 命名的是全局命名空间内的函数 <span class="t-c"><span class="mw-geshi cpp source-cpp">tolower</span></span> 。表达式 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="sy4">::</span><a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a></span></span> 指名 <span class="t-c"><span class="mw-geshi cpp source-cpp">std</span></span> 命名空间(顶层命名空间)中的全局变量 <span class="t-c"><span class="mw-geshi cpp source-cpp">cout</span></span> 。表达式 <span class="t-c"><span class="mw-geshi cpp source-cpp">boost<span class="sy4">::</span><span class="me2">signals2</span><span class="sy4">::</span><span class="me2">connection</span></span></span> 指名的是声明于 <span class="t-c"><span class="mw-geshi cpp source-cpp">signals2</span></span> 命名空间中的类型 <span class="t-c"><span class="mw-geshi cpp source-cpp">connection</span></span> ,前者则声明于命名空间 <span class="t-c"><span class="mw-geshi cpp source-cpp">boost</span></span> 。</p>
|
|
<p>有限定标识符中,可能会需要以关键词 <a href="cpp-keyword-template.html"><tt>template</tt></a> 来消除<a href="cpp-language-dependent_name.html">待决模板名</a>的歧义。</p>
|
|
<p>关于为有限定的标识符进行的名字查找的细节,请参见<a href="cpp-language-qualified_lookup.html">有限定的名字查找</a>。</p>
|
|
<h3><span class="mw-headline" id=".E5.90.8D.E5.AD.97">名字</span></h3>
|
|
<p><i>名字</i>是以下各项之一,用来代表某个实体或者某个标号:</p>
|
|
<ul>
|
|
<li>标识符;</li>
|
|
<li>函数写法的重载运算符的名字( <span class="t-c"><span class="mw-geshi cpp source-cpp">operator<span class="sy2">+</span></span></span> 、 <span class="t-c"><span class="mw-geshi cpp source-cpp"><a href="cpp-memory-new-operator_new.html"><span class="kw687">operator new</span></a></span></span>);</li>
|
|
<li>用户定义的转换函数的名字( <span class="t-c"><span class="mw-geshi cpp source-cpp">operator <span class="kw4">bool</span></span></span>);</li>
|
|
<li>用户定义的字面量运算符的名字( <span class="t-c"><span class="mw-geshi cpp source-cpp">operator <span class="st0">""</span> _km</span></span>);</li>
|
|
<li>模板的名字后随其实参列表( <span class="t-c"><span class="mw-geshi cpp source-cpp">MyTemplate<span class="sy1"><</span><span class="kw4">int</span><span class="sy1">></span></span></span>)。</li>
|
|
</ul>
|
|
<p>每个代表实体的名字都是由<a href="cpp-language-declarations.html">声明</a>引入到程序中来的。代表标号的名字则既可以通过 <a href="cpp-language-goto.html">goto 语句</a>,也可以通过<a href="cpp-language-statements.html#.E6.A0.87.E5.8F.B7">带标号语句</a>引入到程序中来。在多个翻译单元中使用的相同名字,可以根据其<a href="cpp-language-storage_duration.html#.E9.93.BE.E6.8E.A5">链接</a>代表相同或者不同的实体。</p>
|
|
<p>每当编译器在程序中遇到一个未知的名字时,它就会通过进行<a href="cpp-language-lookup.html">名字查找</a>来将其与引入这个名字的声明联系起来,但对模板的声明和定义中的<a href="cpp-language-dependent_name.html">待决名</a>不会这样做。(对于这些名字,编译器需要确定它们命名的是类型、模板还是某些其他实体,这可能需要<a href="cpp-language-dependent_name.html">显式消歧义</a>)。</p>
|
|
<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>
|