247 lines
26 KiB
HTML
247 lines
26 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_expressions 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>和它们的<i>操作数</i>的序列,它指定一项计算。</p>
|
|
<p>表达式的求值可以产生一个结果(比如 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="nu0">2</span><span class="sy2">+</span><span class="nu0">2</span></span></span> 的求值产生结果 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="nu0">4</span></span></span>),也可能产生副作用(比如对 <span class="t-c"><span class="mw-geshi cpp source-cpp"><a href="cpp-io-c-fprintf.html"><span class="kw1845">std::<span class="me2">printf</span></span></a><span class="br0">(</span><span class="st0">"%d"</span>,<span class="nu0">4</span><span class="br0">)</span></span></span> 的求值在标准输出上打印字符 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="st0">'4'</span></span></span>)。</p>
|
|
<h4><span class="mw-headline" id=".E6.A6.82.E8.BF.B0">概述</span></h4>
|
|
<ul>
|
|
<li><a href="cpp-language-value_category.html">值类别</a>(左值 (lvalue)、右值 (rvalue)、泛左值 (glvalue)、纯右值 (prvalue)、亡值 (xvalue))是根据表达式的值所进行的分类</li>
|
|
<li>实参和子表达式的<a href="cpp-language-eval_order.html">求值顺序</a>指定获得中间结果所用的顺序</li>
|
|
</ul>
|
|
<h3><span class="mw-headline" id=".E8.BF.90.E7.AE.97.E7.AC.A6">运算符</span></h3>
|
|
<table class="wikitable">
|
|
<tr style="text-align:center">
|
|
<th colspan="7">常见运算符</th>
|
|
</tr>
|
|
<tr style="text-align:center">
|
|
<td><a href="cpp-language-operator_assignment.html">赋值</a></td>
|
|
<td><a href="cpp-language-operator_incdec.html">自增<br />
|
|
自减</a></td>
|
|
<td><a href="cpp-language-operator_arithmetic.html">算术</a></td>
|
|
<td><a href="cpp-language-operator_logical.html">逻辑</a></td>
|
|
<td><a href="cpp-language-operator_comparison.html">比较</a></td>
|
|
<td><a href="cpp-language-operator_member_access.html">成员访问</a></td>
|
|
<td><a href="cpp-language-operator_other.html">其他</a></td>
|
|
</tr>
|
|
<tr style="text-align:center">
|
|
<td>
|
|
<p><span class="t-c"><span class="mw-geshi cpp source-cpp">a <span class="sy1">=</span> b<br />
|
|
a <span class="sy2">+</span><span class="sy1">=</span> b<br />
|
|
a <span class="sy2">-</span><span class="sy1">=</span> b<br />
|
|
a <span class="sy2">*</span><span class="sy1">=</span> b<br />
|
|
a <span class="sy2">/</span><span class="sy1">=</span> b<br />
|
|
a <span class="sy2">%</span><span class="sy1">=</span> b<br />
|
|
a <span class="sy3">&</span><span class="sy1">=</span> b<br />
|
|
a <span class="sy3">|</span><span class="sy1">=</span> b<br />
|
|
a <span class="sy3">^</span><span class="sy1">=</span> b<br />
|
|
a <span class="sy1"><<=</span> b<br />
|
|
a <span class="sy1">>>=</span> b</span></span></p>
|
|
</td>
|
|
<td>
|
|
<p><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="sy2">++</span>a<br />
|
|
<span class="sy2">--</span>a<br />
|
|
a<span class="sy2">++</span><br />
|
|
a<span class="sy2">--</span></span></span></p>
|
|
</td>
|
|
<td>
|
|
<p><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="sy2">+</span>a<br />
|
|
<span class="sy2">-</span>a<br />
|
|
a <span class="sy2">+</span> b<br />
|
|
a <span class="sy2">-</span> b<br />
|
|
a <span class="sy2">*</span> b<br />
|
|
a <span class="sy2">/</span> b<br />
|
|
a <span class="sy2">%</span> b<br />
|
|
~a<br />
|
|
a <span class="sy3">&</span> b<br />
|
|
a <span class="sy3">|</span> b<br />
|
|
a <span class="sy3">^</span> b<br />
|
|
a <span class="sy1"><<</span> b<br />
|
|
a <span class="sy1">>></span> b</span></span></p>
|
|
</td>
|
|
<td>
|
|
<p><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="sy3">!</span>a<br />
|
|
a <span class="sy3">&&</span> b<br />
|
|
a <span class="sy3">||</span> b</span></span></p>
|
|
</td>
|
|
<td>
|
|
<p><span class="t-c"><span class="mw-geshi cpp source-cpp">a <span class="sy1">==</span> b<br />
|
|
a <span class="sy3">!</span><span class="sy1">=</span> b<br />
|
|
a <span class="sy1"><</span> b<br />
|
|
a <span class="sy1">></span> b<br />
|
|
a <span class="sy1"><=</span> b<br />
|
|
a <span class="sy1">>=</span> b<br />
|
|
a <span class="sy1"><=></span> b</span></span></p>
|
|
</td>
|
|
<td>
|
|
<p><span class="t-c"><span class="mw-geshi cpp source-cpp">a<span class="br0">[</span>b<span class="br0">]</span><br />
|
|
<span class="sy2">*</span>a<br />
|
|
<span class="sy3">&</span>a<br />
|
|
a<span class="sy2">-</span><span class="sy1">></span>b<br />
|
|
a.<span class="me1">b</span><br />
|
|
a<span class="sy2">-</span><span class="sy1">></span><span class="sy2">*</span>b<br />
|
|
a.<span class="sy2">*</span>b</span></span></p>
|
|
</td>
|
|
<td>
|
|
<p><span class="t-c"><span class="mw-geshi cpp source-cpp">a<span class="br0">(</span>...<span class="br0">)</span><br />
|
|
a, b<br />
|
|
<span class="sy4">?</span> <span class="sy4">:</span></span></span></p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th colspan="7">特殊运算符</th>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="7">
|
|
<p><a href="cpp-language-static_cast.html"><tt>static_cast</tt></a> 转换一个类型为另一相关类型<br />
|
|
<a href="cpp-language-dynamic_cast.html"><tt>dynamic_cast</tt></a> 在继承层级中转换<br />
|
|
<a href="cpp-language-const_cast.html"><tt>const_cast</tt></a> 添加或移除 <a href="cpp-language-cv.html">cv</a> 限定符<br />
|
|
<a href="cpp-language-reinterpret_cast.html"><tt>reinterpret_cast</tt></a> 转换类型到无关类型<br />
|
|
<a href="cpp-language-explicit_cast.html">C 风格转型</a> 以 <code>static_cast</code> 、 <code>const_cast</code> 及 <code>reinterpret_cast</code> 的混合转换一个类型到另一类型<br />
|
|
<a href="cpp-language-new.html"><tt>new</tt></a> 创建有动态存储期的对象<br />
|
|
<a href="cpp-language-delete.html"><tt>delete</tt></a> 销毁先前由 new 表达式创建的对象,并释放其所拥有的内存区域<br />
|
|
<a href="cpp-language-sizeof.html"><tt>sizeof</tt></a> 查询类型的大小<br />
|
|
<a href="cpp-language-sizeof....html"><tt>sizeof...</tt></a> 查询<a href="cpp-language-parameter_pack.html">形参包</a>的大小<span class="t-mark-rev t-since-cxx11">(C++11 起)</span><br />
|
|
<a href="cpp-language-typeid.html"><tt>typeid</tt></a> 查询类型的类型信息<br />
|
|
<a href="cpp-language-noexcept.html"><tt>noexcept</tt></a> 查询表达式是否能抛出异常<span class="t-mark-rev t-since-cxx11">(C++11 起)</span><br />
|
|
<a href="cpp-language-alignof.html"><tt>alignof</tt></a> 查询类型的对齐要求<span class="t-mark-rev t-since-cxx11">(C++11 起)</span></p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<ul>
|
|
<li><a href="cpp-language-operator_precedence.html">运算符优先级</a>定义了运算符绑定到其各实参的顺序</li>
|
|
<li><a href="cpp-language-operator_alternative.html">替代表示</a>是一些运算符的其他代用书写方式</li>
|
|
<li><a href="cpp-language-operators.html">运算符重载</a>允许对用户定义的类指定各运算符的行为。</li>
|
|
</ul>
|
|
<h4><span class="mw-headline" id=".E8.BD.AC.E6.8D.A2">转换</span></h4>
|
|
<ul>
|
|
<li><a href="cpp-language-implicit_conversion.html">标准转换</a>为从一个类型到另一类型的隐式转换</li>
|
|
<li><a href="cpp-language-const_cast.html"><code>const_cast</code> 转换</a></li>
|
|
<li><a href="cpp-language-static_cast.html"><code>static_cast</code> 转换</a></li>
|
|
<li><a href="cpp-language-dynamic_cast.html"><code>dynamic_cast</code> 转换</a></li>
|
|
<li><a href="cpp-language-reinterpret_cast.html"><code>reinterpret_cast</code> 转换</a></li>
|
|
<li><a href="cpp-language-explicit_cast.html">显式转型</a>转换,使用 C 风格写法和函数式写法</li>
|
|
<li><a href="cpp-language-cast_operator.html">用户定义转换</a>使得可以指定源自用户定义类的转换</li>
|
|
</ul>
|
|
<h4><span class="mw-headline" id=".E5.86.85.E5.AD.98.E5.88.86.E9.85.8D">内存分配</span></h4>
|
|
<ul>
|
|
<li><a href="cpp-language-new.html">new 表达式</a>动态地分配内存</li>
|
|
<li><a href="cpp-language-delete.html">delete 表达式</a>动态地解分配内存</li>
|
|
</ul>
|
|
<h4><span class="mw-headline" id=".E5.85.B6.E4.BB.96">其他</span></h4>
|
|
<ul>
|
|
<li><a href="cpp-language-constant_expression.html">常量表达式</a>能在编译期求值并在编译期语境(如模板实参、数组大小等等)中使用</li>
|
|
<li><a href="cpp-language-sizeof.html"><code>sizeof</code></a></li>
|
|
<li><a href="cpp-language-alignof.html"><code>alignof</code></a></li>
|
|
<li><a href="cpp-language-typeid.html"><code>typeid</code></a></li>
|
|
<li><a href="cpp-language-throw.html">throw 表达式</a></li>
|
|
</ul>
|
|
<p><br /></p>
|
|
<h3><span class="mw-headline" id=".E5.88.9D.E7.AD.89.E8.A1.A8.E8.BE.BE.E5.BC.8F">初等表达式</span></h3>
|
|
<p>任何运算符的操作数都可以是其他的表达式或初等表达式(例如,<span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="nu0">1</span><span class="sy2">+</span><span class="nu0">2</span><span class="sy2">*</span><span class="nu0">3</span></span></span> 中 operator+ 的操作数是子表达式 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="nu0">2</span><span class="sy2">*</span><span class="nu0">3</span></span></span> 和初等表达式 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="nu0">1</span></span></span>)。</p>
|
|
<p>初等表达式包括以下各项:</p>
|
|
<ul>
|
|
<li>字面量(例如 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="nu0">2</span></span></span> 或 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="st0">"Hello, world"</span></span></span>)</li>
|
|
<li>标识表达式,包括
|
|
<ul>
|
|
<li>经过适当声明的<a href="cpp-language-identifiers.html#.E6.97.A0.E9.99.90.E5.AE.9A.E7.9A.84.E6.A0.87.E8.AF.86.E7.AC.A6">无限定的标识符</a>(例如 <span class="t-c"><span class="mw-geshi cpp source-cpp">n</span></span> 或 <span class="t-c"><span class="mw-geshi cpp source-cpp">cout</span></span>),以及</li>
|
|
<li>经过适当声明的<a href="cpp-language-identifiers.html#.E6.9C.89.E9.99.90.E5.AE.9A.E7.9A.84.E6.A0.87.E8.AF.86.E7.AC.A6">有限定的标识符</a>(例如 <span class="t-lc"><a href="cpp-string-basic_string-npos.html">std::string::npos</a></span>)</li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="cpp-language-lambda.html">lambda 表达式</a> <span class="t-mark-rev t-since-cxx11">(C++11)</span></li>
|
|
<li><a href="cpp-language-fold.html">折叠表达式</a> <span class="t-mark-rev t-since-cxx17">(C++17)</span></li>
|
|
<li><a href="cpp-language-constraints.html">requires 表达式</a> <span class="t-mark-rev t-since-cxx20">(C++20)</span></li>
|
|
</ul>
|
|
<p>括号中的任何表达式也被归类为初等表达式:这确保了括号具有比任何运算符更高的优先级。括号保持值、类型和值类别不变。</p>
|
|
<h4><span class="mw-headline" id=".E5.AD.97.E9.9D.A2.E9.87.8F">字面量</span></h4>
|
|
<p>字面量是 C++ 程序中用以表现嵌入到源代码中的常量值的记号。</p>
|
|
<ul>
|
|
<li><a href="cpp-language-integer_literal.html">整数字面量</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>的数值</li>
|
|
<li><a href="cpp-language-character_literal.html">字符字面量</a>是有下列类型之一的单个字符:</li>
|
|
</ul>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">char</span></span></span> 或 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">wchar_t</span></span></span></li>
|
|
<li><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">char16_t</span></span></span> 或 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">char32_t</span></span></span> <span class="t-mark-rev t-since-cxx11">(C++11 起)</span></li>
|
|
<li><span class="t-c"><span class="mw-geshi cpp source-cpp">char8_t</span></span> <span class="t-mark-rev t-since-cxx20">(C++20 起)</span></li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<ul>
|
|
<li><a href="cpp-language-floating_literal.html">浮点字面量</a>是 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">float</span></span></span>、<span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">double</span></span></span> 或 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">long</span> <span class="kw4">double</span></span></span> 类型的值</li>
|
|
<li><a href="cpp-language-string_literal.html">字符串字面量</a>是有下列类型之一的字符序列:</li>
|
|
</ul>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">const</span> <span class="kw4">char</span><span class="br0">[</span><span class="br0">]</span></span></span> 或 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">const</span> <span class="kw4">wchar_t</span><span class="br0">[</span><span class="br0">]</span></span></span></li>
|
|
<li><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">const</span> <span class="kw4">char16_t</span><span class="br0">[</span><span class="br0">]</span></span></span> 或 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">const</span> <span class="kw4">char32_t</span><span class="br0">[</span><span class="br0">]</span></span></span> <span class="t-mark-rev t-since-cxx11">(C++11 起)</span></li>
|
|
<li><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">const</span> char8_t<span class="br0">[</span><span class="br0">]</span></span></span> <span class="t-mark-rev t-since-cxx20">(C++20 起)</span></li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<ul>
|
|
<li><a href="cpp-language-bool_literal.html">布尔字面量</a>是 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">bool</span></span></span> 类型的值,即 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw2">true</span></span></span> 和 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw2">false</span></span></span></li>
|
|
<li><a href="cpp-language-nullptr.html"><code>nullptr</code></a> 是指针字面量,指定一个空指针值 <span class="t-mark-rev t-since-cxx11">(C++11 起)</span></li>
|
|
<li><a href="cpp-language-user_literal.html">用户定义字面量</a>是用户指定的类型的常量值 <span class="t-mark-rev t-since-cxx11">(C++11 起)</span></li>
|
|
</ul>
|
|
<h3><span class="mw-headline" id=".E4.B8.8D.E6.B1.82.E5.80.BC.E8.A1.A8.E8.BE.BE.E5.BC.8F">不求值表达式</span></h3>
|
|
<p>运算符 <a href="cpp-language-typeid.html"><code>typeid</code></a>、<a href="cpp-language-sizeof.html"><code>sizeof</code></a><span class="t-rev-inl t-since-cxx11"><span>、<a href="cpp-language-noexcept.html"><code>noexcept</code></a> 和 <a href="cpp-language-decltype.html"><code>decltype</code></a></span> <span><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></span></span> 的操作数是不求值表达式(除非运算符为 <code>typeid</code> 而操作数是多态泛左值),因为这些运算符仅查询其操作数的编译期性质。因此,<span class="t-c"><span class="mw-geshi cpp source-cpp"><a href="cpp-types-size_t.html"><span class="kw100">std::<span class="me2">size_t</span></span></a> n <span class="sy1">=</span> sizeof<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="nu0">42</span><span class="br0">)</span><span class="sy4">;</span></span></span> 不进行控制台输出。</p>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx14">
|
|
<td>
|
|
<p>不求值的运算数被当做<i>完整表达式</i>,即便它们在语法上是某个更大的表达式的操作数也是如此(例如,这意味着 <span class="t-c"><span class="mw-geshi cpp source-cpp">sizeof<span class="br0">(</span>T<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span></span></span> 要求 <code>T::~T</code> 可访问)</p>
|
|
</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-cxx20">
|
|
<td>
|
|
<p><a href="cpp-language-constraints.html">requires 表达式</a>也是不求值表达式。</p>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E5.BC.83.E5.80.BC.E8.A1.A8.E8.BE.BE.E5.BC.8F">弃值表达式</span></h3>
|
|
<p><i>弃值表达式</i>是仅用来实施其副作用的表达式。从这种表达式计算的值被舍弃。这样的表达式包括任何<a href="cpp-language-statements.html#.E8.A1.A8.E8.BE.BE.E5.BC.8F.E8.AF.AD.E5.8F.A5">表达式语句</a>的完整表达式,内建逗号运算符的左边的实参,以及转型到类型 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">void</span></span></span> 的转型表达式的实参。</p>
|
|
<p>弃值表达式的计算结果永远不进行数组到指针和函数到指针转换。当且仅当该表达式是 <a href="cpp-language-cv.html">volatile 限定的</a>泛左值,并具有下列形式之一(必须为其内建含义,可以有括号)时,进行左值到右值转换:</p>
|
|
<ul>
|
|
<li>标识表达式 (id-expression)</li>
|
|
<li>数组下标表达式</li>
|
|
<li>类成员访问表达式</li>
|
|
<li>间接寻址</li>
|
|
<li>成员指针操作</li>
|
|
<li>条件表达式,其第二个和第三个操作数都是这些表达式中的一种</li>
|
|
<li>逗号表达式,其右操作数是这些表达式中的一种。</li>
|
|
</ul>
|
|
<p>此外,若该左值拥有 volatile 限定的类类型,则要求用 volatile 复制构造函数来初始化作为结果的右值临时量。</p>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx17">
|
|
<td>
|
|
<p>如果表达式(经过可能会发生的任何左值向右值转换之后)是非 void 纯右值,则进行<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>
|
|
<p>当表达式丢弃了声明为 <code>[[<a href="cpp-language-attributes-nodiscard.html">nodiscard</a>]]</code> 的值,而它不是转型为 <code>void</code> 的表达式时,编译器可以发布警告。</p>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="visualClear"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|