上传cppreference
This commit is contained in:
482
web/cppreference-zh/chmhelp/cpp-language-pointer.html
Normal file
482
web/cppreference-zh/chmhelp/cpp-language-pointer.html
Normal file
@@ -0,0 +1,482 @@
|
||||
<!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_pointer 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>声明指针或指向成员指针类型的变量。</p>
|
||||
<h3><span class="mw-headline" id=".E8.AF.AD.E6.B3.95">语法</span></h3>
|
||||
<p>指针的声明是简单声明,其<a href="cpp-language-declarations.html">声明符</a>拥有下列形式</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><span class="t-mark">(可选)</span> <span class="t-spar">cv限定符</span><span class="t-mark">(可选)</span> <span class="t-spar">声明符</span></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><span class="t-spar">嵌套名说明符</span> <code><b>*</b></code> <span class="t-spar">属性</span><span class="t-mark">(可选)</span> <span class="t-spar">cv限定符</span><span class="t-mark">(可选)</span> <span class="t-spar">声明符</span></td>
|
||||
<td>(2)</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> <b>指针声明符</b>:声明 <span class="t-c"><span class="mw-geshi cpp source-cpp">S<span class="sy2">*</span> D<span class="sy4">;</span></span></span> 将 <code>D</code> 声明为指向 <span class="t-spar">嵌套名说明符</span> <code>S</code> 所确定类型的指针。</div>
|
||||
<div class="t-li1"><span class="t-li">2)</span> <b>成员指针声明符</b>:声明 <span class="t-c"><span class="mw-geshi cpp source-cpp">S C<span class="sy4">::</span><span class="sy2">*</span> D<span class="sy4">;</span></span></span> 将 <code>D</code> 声明为指向 <code>C</code> 的 <span class="t-spar">嵌套名说明符</span> <code>S</code> 所确定类型的非静态数据成员的指针。</div>
|
||||
<table class="t-par-begin">
|
||||
<tr class="t-par">
|
||||
<td><span class="t-spar">嵌套名说明符</span></td>
|
||||
<td>-</td>
|
||||
<td><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">名字和作用域解析运算符 <code><b>::</b></code> 的序列</a></td>
|
||||
</tr>
|
||||
<tr class="t-par">
|
||||
<td><span class="t-spar">属性</span></td>
|
||||
<td>-</td>
|
||||
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span> 可选的<a href="cpp-language-attributes.html">属性</a>列表</td>
|
||||
</tr>
|
||||
<tr class="t-par">
|
||||
<td><span class="t-spar">cv限定符</span></td>
|
||||
<td>-</td>
|
||||
<td>应用到被声明指针的 const/volatile 限定(而并非被指向类型,其限定是 <span class="t-spar">声明说明符序列</span> 的一部分)</td>
|
||||
</tr>
|
||||
<tr class="t-par">
|
||||
<td><span class="t-spar">声明符</span></td>
|
||||
<td>-</td>
|
||||
<td>除引用声明符之外的任意<a href="cpp-language-declarations.html">声明符</a>(无指向引用的指针)。它可以是另一指针声明符(允许指向指针的指针)</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>不存在指向<a href="cpp-language-reference.html">引用</a>的指针和指向<a href="cpp-language-bit_field.html">位域</a>的指针。 当没有详述地提及“指针”时,通常不包含指向(非静态)成员的指针。</p>
|
||||
<h3><span class="mw-headline" id=".E6.8C.87.E9.92.88">指针</span></h3>
|
||||
<p>指针类型的值是下列之一:</p>
|
||||
<ul>
|
||||
<li><i>指向对象或函数的指针</i>(此时我们说该指针<i>指向</i>函数或对象),或</li>
|
||||
<li><i>对象末尾后指针</i>,或</li>
|
||||
<li>该类型的<i><a href="cpp-language-pointer.html#.E7.A9.BA.E6.8C.87.E9.92.88">空指针值</a></i>,或</li>
|
||||
<li><i>无效指针值</i>。</li>
|
||||
</ul>
|
||||
<p>指向对象的指针<i>表示</i>该对象所占用的内存的首字节的地址。对象的末尾后指针<i>表示</i>,内存中该对象所占用的存储之后的首个字节的地址。</p>
|
||||
<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> C <span class="br0">{</span>
|
||||
<span class="kw4">int</span> x, y<span class="sy4">;</span>
|
||||
<span class="br0">}</span> c<span class="sy4">;</span>
|
||||
|
||||
<span class="kw4">int</span><span class="sy2">*</span> px <span class="sy1">=</span> <span class="sy3">&</span>c.<span class="me1">x</span><span class="sy4">;</span> <span class="co1">// px 的值为“指向 c.x 的指针”</span>
|
||||
<span class="kw4">int</span><span class="sy2">*</span> pxe<span class="sy1">=</span> px <span class="sy2">+</span> <span class="nu0">1</span><span class="sy4">;</span> <span class="co1">// pxe 的值为“ c.x 的尾后指针”</span>
|
||||
<span class="kw4">int</span><span class="sy2">*</span> py <span class="sy1">=</span> <span class="sy3">&</span>c.<span class="me1">y</span><span class="sy4">;</span> <span class="co1">// py 的值为“指向 c.y 的指针”</span>
|
||||
|
||||
<a href="cpp-error-assert.html"><span class="kw774">assert</span></a><span class="br0">(</span>pxe <span class="sy1">==</span> py<span class="br0">)</span><span class="sy4">;</span> <span class="co1">// == 测试两个指针是否表示相同地址</span>
|
||||
<span class="co1">// 可能或可能不引发断言</span>
|
||||
|
||||
<span class="sy2">*</span>pxe <span class="sy1">=</span> <span class="nu0">1</span><span class="sy4">;</span> <span class="co1">// 即使未引发断言也是未定义行为</span></pre></div>
|
||||
</div>
|
||||
<p>通过无效指针值间接寻址,和将无效指针值传递给解分配函数均拥有未定义行为。无效指针值的任何其他用法拥有由实现定义的行为。部分实现会将复制无效指针值的行为定义为造成由系统生成的运行时错误。</p>
|
||||
<h4><span class="mw-headline" id=".E5.AF.B9.E8.B1.A1.E6.8C.87.E9.92.88">对象指针</span></h4>
|
||||
<p>对象指针能以应用于任何对象类型(包含另一指针类型)的表达式的<a href="cpp-language-operator_member_access.html">取址运算符</a>的返回值初始化:</p>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="kw4">int</span> n<span class="sy4">;</span>
|
||||
<span class="kw4">int</span><span class="sy2">*</span> np <span class="sy1">=</span> <span class="sy3">&</span>n<span class="sy4">;</span> <span class="co1">// 指向 int 的指针</span>
|
||||
<span class="kw4">int</span><span class="sy2">*</span> <span class="kw4">const</span><span class="sy2">*</span> npp <span class="sy1">=</span> <span class="sy3">&</span>np<span class="sy4">;</span> <span class="co1">// 指向【指向非 const int 的 const 指针】的非 const 指针</span>
|
||||
|
||||
<span class="kw4">int</span> a<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span class="sy4">;</span>
|
||||
<span class="kw4">int</span> <span class="br0">(</span><span class="sy2">*</span>ap<span class="br0">)</span><span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span> <span class="sy1">=</span> <span class="sy3">&</span>a<span class="sy4">;</span> <span class="co1">// 指向含有 int 的数组的指针</span>
|
||||
|
||||
<span class="kw1">struct</span> S <span class="br0">{</span> <span class="kw4">int</span> n<span class="sy4">;</span> <span class="br0">}</span><span class="sy4">;</span>
|
||||
S s <span class="sy1">=</span> <span class="br0">{</span><span class="nu0">1</span><span class="br0">}</span><span class="sy4">;</span>
|
||||
<span class="kw4">int</span><span class="sy2">*</span> sp <span class="sy1">=</span> <span class="sy3">&</span>s.<span class="me1">n</span><span class="sy4">;</span> <span class="co1">// 指向作为 s 的成员的 int 的指针</span></pre></div>
|
||||
</div>
|
||||
<p>对象指针可作为内建间接寻址运算符(一元 <code>operator*</code>)的操作数,并返回指代被指向对象的<a href="cpp-language-value_category.html">左值表达式</a>:</p>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="kw4">int</span> n<span class="sy4">;</span>
|
||||
<span class="kw4">int</span><span class="sy2">*</span> p <span class="sy1">=</span> <span class="sy3">&</span>n<span class="sy4">;</span> <span class="co1">// 指向 n 的指针</span>
|
||||
<span class="kw4">int</span><span class="sy3">&</span> r <span class="sy1">=</span> <span class="sy2">*</span>p<span class="sy4">;</span> <span class="co1">// 绑定到指代 n 的左值表达式的引用</span>
|
||||
r <span class="sy1">=</span> <span class="nu0">7</span><span class="sy4">;</span> <span class="co1">// 在 n 存储 int 7</span>
|
||||
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="sy2">*</span>p<span class="sy4">;</span> <span class="co1">// 左值到右值隐式转换从 n 读取值</span></pre></div>
|
||||
</div>
|
||||
<p>指向类对象的指针也能作为成员访问运算符 <a href="cpp-language-operator_member_access.html#.E5.86.85.E5.BB.BA.E7.9A.84.E6.88.90.E5.91.98.E8.AE.BF.E9.97.AE.E8.BF.90.E7.AE.97.E7.AC.A6">operator-></a> 和 <a href="cpp-language-operator_member_access.html#.E5.86.85.E5.BB.BA.E7.9A.84.E6.88.90.E5.91.98.E6.8C.87.E9.92.88.E8.AE.BF.E9.97.AE.E8.BF.90.E7.AE.97.E7.AC.A6">operator->*</a> 的左侧操作数。</p>
|
||||
<p>由于存在<a href="cpp-language-implicit_conversion.html">数组到指针</a>的隐式转换,可以以数组类型的表达式初始化指向数组首元素的指针:</p>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="kw4">int</span> a<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span class="sy4">;</span>
|
||||
<span class="kw4">int</span><span class="sy2">*</span> p1 <span class="sy1">=</span> a<span class="sy4">;</span> <span class="co1">// 指向数组 a 首元素 a[0](一个 int)的指针</span>
|
||||
|
||||
<span class="kw4">int</span> b<span class="br0">[</span><span class="nu0">6</span><span class="br0">]</span><span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span><span class="br0">[</span><span class="nu0">8</span><span class="br0">]</span><span class="sy4">;</span>
|
||||
<span class="kw4">int</span> <span class="br0">(</span><span class="sy2">*</span>p2<span class="br0">)</span><span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span><span class="br0">[</span><span class="nu0">8</span><span class="br0">]</span> <span class="sy1">=</span> b<span class="sy4">;</span> <span class="co1">// 指向数组 b 首元素 b[0] 的指针,</span>
|
||||
<span class="co1">// 被指者为含有 3 个【含有 8 个 int 元素的数组】元素的数组</span></pre></div>
|
||||
</div>
|
||||
<p>由于存在指针的<a href="cpp-language-implicit_conversion.html">派生类到基类</a>的隐式转换,可以以派生类的地址初始化指向基类的指针:</p>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="kw1">struct</span> Base <span class="br0">{</span><span class="br0">}</span><span class="sy4">;</span>
|
||||
<span class="kw1">struct</span> Derived <span class="sy4">:</span> Base <span class="br0">{</span><span class="br0">}</span><span class="sy4">;</span>
|
||||
|
||||
Derived d<span class="sy4">;</span>
|
||||
Base<span class="sy2">*</span> p <span class="sy1">=</span> <span class="sy3">&</span>d<span class="sy4">;</span></pre></div>
|
||||
</div>
|
||||
<p>如果 <code>Derived</code> 是<a href="cpp-language-object.html#.E5.A4.9A.E6.80.81.E5.AF.B9.E8.B1.A1">多态的</a>,那么这种指针可用于进行<a href="cpp-language-virtual.html">虚函数调用</a>。</p>
|
||||
<p>某些<a href="cpp-language-operator_arithmetic.html#.E5.8A.A0.E6.B3.95.E6.80.A7.E8.BF.90.E7.AE.97.E7.AC.A6">加法、减法</a>、<a href="cpp-language-operator_incdec.html">自增和自减</a>运算符对于指向数组元素的指针有定义:这种指针满足<a href="cpp-named_req-RandomAccessIterator.html"><span style="font-style:italic">老式随机访问迭代器</span> <span style="font-family: Georgia, 'DejaVu Serif', serif; font-style:italic">(LegacyRandomAccessIterator)</span></a> 要求,并使得 C++ 库<a href="cpp-algorithm.html">算法</a>可以用于原始数组。</p>
|
||||
<p>某些情况下,<a href="cpp-language-operator_comparison.html#.E6.8C.87.E9.92.88.E6.AF.94.E8.BE.83.E8.BF.90.E7.AE.97.E7.AC.A6">比较运算符</a>对指针有定义:两个表示相同地址的指针比较相等,两个空指针值比较相等,指向同一数组中的元素的指针的比较与各元素的数组下标的比较方式相同,而指向拥有相同<a href="cpp-language-access.html">成员访问</a>的非静态数据成员的指针以各成员的声明顺序进行比较。</p>
|
||||
<p>多数实现也为随机来源的指针提供<a href="https://en.wikipedia.org/wiki/Total_order#Strict_total_order" class="extiw" title="enwiki:Total order">严格全序</a>,例如将它们实现为连续虚拟地址空间中的地址。未能做到的实现(例如,其中并非指针的所有位都是内存地址的一部分因而在比较时必须忽略之,或者要求附带的计算,或者指针与整数并非一对一关系),为指针提供了具有此项保证的 <span class="t-lc"><a href="cpp-utility-functional-less.html">std::less</a></span> 特化。这使得可在关联容器(如 <span class="t-lc"><a href="cpp-container-set.html">std::set</a></span> 或 <span class="t-lc"><a href="cpp-container-map.html">std::map</a></span>)中使用所有随机来源的指针。</p>
|
||||
<h4><span class="mw-headline" id=".E6.8C.87.E5.90.91_void_.E7.9A.84.E6.8C.87.E9.92.88">指向 void 的指针</span></h4>
|
||||
<p>指向任意类型对象的指针都可以被<a href="cpp-language-implicit_conversion.html">隐式转换成</a>指向 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">void</span></span></span> 的指针(可有 <a href="cpp-language-cv.html">cv 限定</a>);不改变其值。逆向的转换要求 <a href="cpp-language-static_cast.html">static_cast</a> 或<a href="cpp-language-explicit_cast.html">显式转型</a>,并生成其原指针值:</p>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="kw4">int</span> n <span class="sy1">=</span> <span class="nu0">1</span><span class="sy4">;</span>
|
||||
<span class="kw4">int</span><span class="sy2">*</span> p1 <span class="sy1">=</span> <span class="sy3">&</span>n<span class="sy4">;</span>
|
||||
<span class="kw4">void</span><span class="sy2">*</span> pv <span class="sy1">=</span> p1<span class="sy4">;</span>
|
||||
<span class="kw4">int</span><span class="sy2">*</span> p2 <span class="sy1">=</span> <span class="kw1">static_cast</span><span class="sy1"><</span><span class="kw4">int</span><span class="sy2">*</span><span class="sy1">></span><span class="br0">(</span>pv<span class="br0">)</span><span class="sy4">;</span>
|
||||
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="sy2">*</span>p2 <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="co1">// 打印 1</span></pre></div>
|
||||
</div>
|
||||
<p>如果原指针指向某多态类型对象中的基类子对象,则可用 <a href="cpp-language-dynamic_cast.html">dynamic_cast</a> 获得指向最终派生类型的完整对象的 <code>void*</code>。</p>
|
||||
<p>指向 void 的指针与指向 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">char</span></span></span> 的指针拥有相同的大小、表示及对齐。</p>
|
||||
<p>void 指针被用来传递未知类型的对象,这在 C 接口中常见:<span class="t-lc"><a href="cpp-memory-c-malloc.html">std::malloc</a></span> 返回 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">void</span><span class="sy2">*</span></span></span>,<span class="t-lc"><a href="cpp-algorithm-qsort.html">std::qsort</a></span> 期待接受两个 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">const</span> <span class="kw4">void</span><span class="sy2">*</span></span></span> 参数的用户提供回调。<a rel="nofollow" class="external text" href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_create.html">pthread_create</a> 期待接受并返回 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">void</span><span class="sy2">*</span></span></span> 的用户提供的回调。所有情况下,调用方负责在使用前将指针转型到正确类型。</p>
|
||||
<h4><span class="mw-headline" id=".E5.87.BD.E6.95.B0.E6.8C.87.E9.92.88">函数指针</span></h4>
|
||||
<p>函数指针能以非成员函数或静态成员函数的地址初始化。由于存在<a href="cpp-language-implicit_conversion.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="kw4">int</span><span class="br0">)</span><span class="sy4">;</span>
|
||||
<span class="kw4">void</span> <span class="br0">(</span><span class="sy2">*</span>p1<span class="br0">)</span><span class="br0">(</span><span class="kw4">int</span><span class="br0">)</span> <span class="sy1">=</span> <span class="sy3">&</span>f<span class="sy4">;</span>
|
||||
<span class="kw4">void</span> <span class="br0">(</span><span class="sy2">*</span>p2<span class="br0">)</span><span class="br0">(</span><span class="kw4">int</span><span class="br0">)</span> <span class="sy1">=</span> f<span class="sy4">;</span> <span class="co1">// 与 &f 相同</span></pre></div>
|
||||
</div>
|
||||
<p>不同于函数或函数的引用,函数指针是对象,从而能存储于数组、被复制、被赋值等。</p>
|
||||
<table class="wikitable">
|
||||
<tr>
|
||||
<th>语法</th>
|
||||
<th>含义</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">int</span> <span class="br0">(</span><span class="sy2">*</span> f<span class="br0">)</span><span class="br0">(</span><span class="br0">)</span></span></span></td>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">f</span></span> 是一个指向一个【原型为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">int</span> func<span class="br0">(</span><span class="br0">)</span></span></span> 的函数】的指针。</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">int</span> <span class="br0">(</span><span class="sy2">*</span> f<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><span class="br0">(</span><span class="br0">)</span></span></span></td>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">f</span></span> 是一个无参且返回一个【指向一个原型为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">int</span> func<span class="br0">(</span><span class="br0">)</span></span></span> 的函数的指针】的函数。</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">int</span> <span class="sy2">*</span> f<span class="br0">(</span><span class="br0">)</span></span></span></td>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">f</span></span> 是一个无参且返回一个【指向 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">int</span></span></span> 的指针】的函数。</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">int</span> <span class="br0">(</span><span class="sy2">*</span> a<span class="br0">[</span><span class="br0">]</span><span class="br0">)</span><span class="br0">(</span><span class="br0">)</span></span></span></td>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">a</span></span> 是一个含有【指向原型为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">int</span> func<span class="br0">(</span><span class="br0">)</span></span></span> 的函数的指针】元素的数组。</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">int</span> <span class="br0">(</span><span class="sy2">*</span> f<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><span class="br0">[</span><span class="br0">]</span></span></span></td>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">f</span></span> 是一个无参且返回一个【指向一个含有 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">int</span></span></span> 元素的数组】的函数。</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">int</span> <span class="br0">(</span>f<span class="br0">[</span><span class="br0">]</span><span class="br0">)</span><span class="br0">(</span><span class="br0">)</span></span></span></td>
|
||||
<td><i><b>非法</b></i>。函数无法作为数组元素。</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">int</span> <span class="sy2">*</span> <span class="kw4">const</span> <span class="sy2">*</span><span class="br0">(</span><span class="sy2">*</span>g<span class="br0">)</span><span class="br0">(</span><span class="kw4">float</span><span class="br0">)</span></span></span></td>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">g</span></span> 是一个指向一个【原型为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">int</span> <span class="sy2">*</span> <span class="kw4">const</span> <span class="sy2">*</span> func<span class="br0">(</span><span class="kw4">float</span><span class="br0">)</span></span></span> 的函数】的指针,
|
||||
<p>该函数的返回值 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">int</span> <span class="sy2">*</span> <span class="kw4">const</span> <span class="sy2">*</span></span></span> 是一个指向一个【指向 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">int</span></span></span> 的只读指针】的指针。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>要了解更多关于函数,指针和函数指针的声明的信息,可参考<a href="cpp-language-declarations.html">声明</a>。</p>
|
||||
<p>函数指针可用作<a href="cpp-language-operator_other.html">函数调用运算符</a>的左侧操作数,这会调用被指向的函数:</p>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="kw4">int</span> f<span class="br0">(</span><span class="kw4">int</span> n<span class="br0">)</span>
|
||||
<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> n <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
||||
<span class="kw1">return</span> n <span class="sy2">*</span> n<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="kw4">int</span> <span class="br0">(</span><span class="sy2">*</span>p<span class="br0">)</span><span class="br0">(</span><span class="kw4">int</span><span class="br0">)</span> <span class="sy1">=</span> f<span class="sy4">;</span>
|
||||
<span class="kw4">int</span> x <span class="sy1">=</span> p<span class="br0">(</span><span class="nu0">7</span><span class="br0">)</span><span class="sy4">;</span>
|
||||
<span class="br0">}</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="kw4">int</span> f<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span>
|
||||
<span class="kw4">int</span> <span class="br0">(</span><span class="sy2">*</span>p<span class="br0">)</span><span class="br0">(</span><span class="br0">)</span> <span class="sy1">=</span> f<span class="sy4">;</span> <span class="co1">// 指针 p 指向 f</span>
|
||||
<span class="kw4">int</span> <span class="br0">(</span><span class="sy3">&</span>r<span class="br0">)</span><span class="br0">(</span><span class="br0">)</span> <span class="sy1">=</span> <span class="sy2">*</span>p<span class="sy4">;</span> <span class="co1">// 将标识 f 的左值绑定到引用</span>
|
||||
r<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 通过左值引用调用函数 f</span>
|
||||
<span class="br0">(</span><span class="sy2">*</span>p<span class="br0">)</span><span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 通过函数左值调用函数 f</span>
|
||||
p<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 直接通过指针调用函数 f</span></pre></div>
|
||||
</div>
|
||||
<p>如果只有一个重载匹配指针类型,那么函数指针可以从可包含函数、函数模板特化及函数模板的一个重载集进行初始化(细节见<a href="cpp-language-overloaded_address.html">重载函数的地址</a>):</p>
|
||||
<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">typename</span> T<span class="sy1">></span> T f<span class="br0">(</span>T n<span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</span> n<span class="sy4">;</span> <span class="br0">}</span>
|
||||
<span class="kw4">double</span> f<span class="br0">(</span><span class="kw4">double</span> n<span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</span> n<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="kw4">int</span> <span class="br0">(</span><span class="sy2">*</span>p<span class="br0">)</span><span class="br0">(</span><span class="kw4">int</span><span class="br0">)</span> <span class="sy1">=</span> f<span class="sy4">;</span> <span class="co1">// 实例化并选择 f<int></span>
|
||||
<span class="br0">}</span></pre></div>
|
||||
</div>
|
||||
<p><a href="cpp-language-operator_comparison.html#.E6.8C.87.E9.92.88.E6.AF.94.E8.BE.83.E8.BF.90.E7.AE.97.E7.AC.A6">相等比较运算符</a>对于函数指针有定义(如果指向同一函数,那么它们比较相等)。</p>
|
||||
<h3><span class="mw-headline" id=".E6.88.90.E5.91.98.E6.8C.87.E9.92.88">成员指针</span></h3>
|
||||
<h4><span class="mw-headline" id=".E6.95.B0.E6.8D.AE.E6.88.90.E5.91.98.E6.8C.87.E9.92.88">数据成员指针</span></h4>
|
||||
<p>指向作为类 <code>C</code> 的成员的非静态数据成员 <code>m</code> 的指针,能准确地以表达式 <code>&C::m</code> 初始化。在 C 的成员函数中,如 <code>&(C::m)</code> 或 <code>&m</code> 这样的表达式不构成指向成员指针。</p>
|
||||
<p>这种指针能用作<a href="cpp-language-operator_member_access.html">成员指针访问运算符</a> <code>operator.*</code> 与 <code>operator->*</code> 的右侧操作数:</p>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="kw1">struct</span> C <span class="br0">{</span> <span class="kw4">int</span> m<span class="sy4">;</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>
|
||||
<span class="kw4">int</span> C<span class="sy4">::</span><span class="sy2">*</span> p <span class="sy1">=</span> <span class="sy3">&</span>C<span class="sy4">::</span><span class="me2">m</span><span class="sy4">;</span> <span class="co1">// 指向类 C 的数据成员 m</span>
|
||||
C c <span class="sy1">=</span> <span class="br0">{</span><span class="nu0">7</span><span class="br0">}</span><span class="sy4">;</span>
|
||||
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> c.<span class="sy2">*</span>p <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="co1">// 打印 7</span>
|
||||
C<span class="sy2">*</span> cp <span class="sy1">=</span> <span class="sy3">&</span>c<span class="sy4">;</span>
|
||||
cp<span class="sy2">-</span><span class="sy1">></span>m <span class="sy1">=</span> <span class="nu0">10</span><span class="sy4">;</span>
|
||||
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> cp<span class="sy2">-</span><span class="sy1">></span><span class="sy2">*</span>p <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="co1">// 打印 10</span>
|
||||
<span class="br0">}</span></pre></div>
|
||||
</div>
|
||||
<p>指向一个可访问且无歧义的非虚基类的数据成员的指针,可以<a href="cpp-language-implicit_conversion.html">隐式转换</a>成指向派生类的同一数据成员的指针:</p>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="kw1">struct</span> Base <span class="br0">{</span> <span class="kw4">int</span> m<span class="sy4">;</span> <span class="br0">}</span><span class="sy4">;</span>
|
||||
<span class="kw1">struct</span> Derived <span class="sy4">:</span> Base <span class="br0">{</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>
|
||||
<span class="kw4">int</span> Base<span class="sy4">::</span><span class="sy2">*</span> bp <span class="sy1">=</span> <span class="sy3">&</span>Base<span class="sy4">::</span><span class="me2">m</span><span class="sy4">;</span>
|
||||
<span class="kw4">int</span> Derived<span class="sy4">::</span><span class="sy2">*</span> dp <span class="sy1">=</span> bp<span class="sy4">;</span>
|
||||
Derived d<span class="sy4">;</span>
|
||||
d.<span class="me1">m</span> <span class="sy1">=</span> <span class="nu0">1</span><span class="sy4">;</span>
|
||||
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> d.<span class="sy2">*</span>dp <span class="sy1"><<</span> <span class="st0">' '</span> <span class="sy1"><<</span> d.<span class="sy2">*</span>bp <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="co1">// 打印 1 1</span>
|
||||
<span class="br0">}</span></pre></div>
|
||||
</div>
|
||||
<p>相反方向的转换,即从指向派生类的数据成员的指针到指向无歧义非虚基类的数据成员的指针,允许由 <a href="cpp-language-static_cast.html">static_cast</a> 和<a href="cpp-language-explicit_cast.html">显式转型</a>来进行,即使基类并无该成员(但当用该指针访问时,最终派生类中有):</p>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="kw1">struct</span> Base <span class="br0">{</span><span class="br0">}</span><span class="sy4">;</span>
|
||||
<span class="kw1">struct</span> Derived <span class="sy4">:</span> Base <span class="br0">{</span> <span class="kw4">int</span> m<span class="sy4">;</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>
|
||||
<span class="kw4">int</span> Derived<span class="sy4">::</span><span class="sy2">*</span> dp <span class="sy1">=</span> <span class="sy3">&</span>Derived<span class="sy4">::</span><span class="me2">m</span><span class="sy4">;</span>
|
||||
<span class="kw4">int</span> Base<span class="sy4">::</span><span class="sy2">*</span> bp <span class="sy1">=</span> <span class="kw1">static_cast</span><span class="sy1"><</span><span class="kw4">int</span> Base<span class="sy4">::</span><span class="sy2">*</span><span class="sy1">></span><span class="br0">(</span>dp<span class="br0">)</span><span class="sy4">;</span>
|
||||
|
||||
Derived d<span class="sy4">;</span>
|
||||
d.<span class="me1">m</span> <span class="sy1">=</span> <span class="nu0">7</span><span class="sy4">;</span>
|
||||
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> d.<span class="sy2">*</span>bp <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="co1">// OK:打印 7</span>
|
||||
|
||||
Base b<span class="sy4">;</span>
|
||||
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> b.<span class="sy2">*</span>bp <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="co1">// 未定义行为</span>
|
||||
<span class="br0">}</span></pre></div>
|
||||
</div>
|
||||
<p>成员指针的被指向类型也可以是成员指针自身:成员指针可为多级,而且在每级可以有不同的 cv 限定。指针和成员指针的混合也可以多级组合:</p>
|
||||
<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>
|
||||
<span class="kw4">int</span> m<span class="sy4">;</span>
|
||||
<span class="co1">// 指向非 const 成员的 const 指针</span>
|
||||
<span class="kw4">int</span> A<span class="sy4">::</span><span class="sy2">*</span> <span class="kw4">const</span> p<span class="sy4">;</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>
|
||||
<span class="co1">// 指向(A 的)数据成员的非 const 指针</span>
|
||||
<span class="co1">// 该成员是一个指向【(A 的)非 const 成员】的 const 指针</span>
|
||||
<span class="kw4">int</span> A<span class="sy4">::</span><span class="sy2">*</span> <span class="kw4">const</span> A<span class="sy4">::</span><span class="sy2">*</span> p1 <span class="sy1">=</span> <span class="sy3">&</span>A<span class="sy4">::</span><span class="me2">p</span><span class="sy4">;</span>
|
||||
|
||||
<span class="kw4">const</span> A a <span class="sy1">=</span> <span class="br0">{</span><span class="nu0">1</span>, <span class="sy3">&</span>A<span class="sy4">::</span><span class="me2">m</span><span class="br0">}</span><span class="sy4">;</span>
|
||||
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> a.<span class="sy2">*</span><span class="br0">(</span>a.<span class="sy2">*</span>p1<span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="co1">// 打印 1</span>
|
||||
|
||||
<span class="co1">// 指向一个【指向(A 的)非 const 成员的 const 指针】的常规非 const 指针</span>
|
||||
<span class="kw4">int</span> A<span class="sy4">::</span><span class="sy2">*</span> <span class="kw4">const</span><span class="sy2">*</span> p2 <span class="sy1">=</span> <span class="sy3">&</span>a.<span class="me1">p</span><span class="sy4">;</span>
|
||||
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> a.<span class="sy2">**</span>p2 <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="co1">// 打印 1</span>
|
||||
<span class="br0">}</span></pre></div>
|
||||
</div>
|
||||
<h4><span class="mw-headline" id=".E6.88.90.E5.91.98.E5.87.BD.E6.95.B0.E6.8C.87.E9.92.88">成员函数指针</span></h4>
|
||||
<p>指向作为类 <code>C</code> 的成员的非静态成员函数 <code>f</code> 的指针,能准确地以表达式 <code>&C::f</code> 初始化。在 <code>C</code> 的成员函数内,如 <code>&(C::f)</code> 或 <code>&f</code>,这样的表达式不构成成员函数指针。</p>
|
||||
<p>这种指针可以用作<a href="cpp-language-operator_member_access.html">成员指针访问运算符</a> <code>operator.*</code> 与 <code>operator->*</code> 的右操作数。其<a href="cpp-language-value_category.html#.E6.9C.AA.E5.86.B3.E6.88.90.E5.91.98.E5.87.BD.E6.95.B0.E8.B0.83.E7.94.A8">结果表达式</a>只能用作函数调用运算符的左侧操作数:</p>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="kw1">struct</span> C
|
||||
<span class="br0">{</span>
|
||||
<span class="kw4">void</span> f<span class="br0">(</span><span class="kw4">int</span> n<span class="br0">)</span> <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> n <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="br0">}</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>
|
||||
<span class="kw4">void</span> <span class="br0">(</span>C<span class="sy4">::</span><span class="sy2">*</span> p<span class="br0">)</span><span class="br0">(</span><span class="kw4">int</span><span class="br0">)</span> <span class="sy1">=</span> <span class="sy3">&</span>C<span class="sy4">::</span><span class="me2">f</span><span class="sy4">;</span> <span class="co1">// 指向类 C 的成员函数 f 的指针</span>
|
||||
C c<span class="sy4">;</span>
|
||||
<span class="br0">(</span>c.<span class="sy2">*</span>p<span class="br0">)</span><span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 打印 1</span>
|
||||
C<span class="sy2">*</span> cp <span class="sy1">=</span> <span class="sy3">&</span>c<span class="sy4">;</span>
|
||||
<span class="br0">(</span>cp<span class="sy2">-</span><span class="sy1">></span><span class="sy2">*</span>p<span class="br0">)</span><span class="br0">(</span><span class="nu0">2</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 打印 2</span>
|
||||
<span class="br0">}</span></pre></div>
|
||||
</div>
|
||||
<p><br />
|
||||
指向基类的成员函数的指针可以<a href="cpp-language-implicit_conversion.html">隐式转换</a>成指向派生类的同一成员函数的指针:</p>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="kw1">struct</span> Base
|
||||
<span class="br0">{</span>
|
||||
<span class="kw4">void</span> f<span class="br0">(</span><span class="kw4">int</span> n<span class="br0">)</span> <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> n <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="br0">}</span>
|
||||
<span class="br0">}</span><span class="sy4">;</span>
|
||||
<span class="kw1">struct</span> Derived <span class="sy4">:</span> Base <span class="br0">{</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>
|
||||
<span class="kw4">void</span> <span class="br0">(</span>Base<span class="sy4">::</span><span class="sy2">*</span> bp<span class="br0">)</span><span class="br0">(</span><span class="kw4">int</span><span class="br0">)</span> <span class="sy1">=</span> <span class="sy3">&</span>Base<span class="sy4">::</span><span class="me2">f</span><span class="sy4">;</span>
|
||||
<span class="kw4">void</span> <span class="br0">(</span>Derived<span class="sy4">::</span><span class="sy2">*</span> dp<span class="br0">)</span><span class="br0">(</span><span class="kw4">int</span><span class="br0">)</span> <span class="sy1">=</span> bp<span class="sy4">;</span>
|
||||
Derived d<span class="sy4">;</span>
|
||||
<span class="br0">(</span>d.<span class="sy2">*</span>dp<span class="br0">)</span><span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span><span class="sy4">;</span>
|
||||
<span class="br0">(</span>d.<span class="sy2">*</span>bp<span class="br0">)</span><span class="br0">(</span><span class="nu0">2</span><span class="br0">)</span><span class="sy4">;</span>
|
||||
<span class="br0">}</span></pre></div>
|
||||
</div>
|
||||
<p>相反方向的转换,即从指向派生类的成员函数的指针到指向无歧义非虚基类的成员函数的指针,允许由 <a href="cpp-language-static_cast.html">static_cast</a> 与<a href="cpp-language-explicit_cast.html">显式转型</a>来进行,即使基类没有该成员函数(但在用该指针进行访问时,最终派生类有):</p>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="kw1">struct</span> Base <span class="br0">{</span><span class="br0">}</span><span class="sy4">;</span>
|
||||
<span class="kw1">struct</span> Derived <span class="sy4">:</span> Base
|
||||
<span class="br0">{</span>
|
||||
<span class="kw4">void</span> f<span class="br0">(</span><span class="kw4">int</span> n<span class="br0">)</span> <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> n <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span> <span class="br0">}</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>
|
||||
<span class="kw4">void</span> <span class="br0">(</span>Derived<span class="sy4">::</span><span class="sy2">*</span> dp<span class="br0">)</span><span class="br0">(</span><span class="kw4">int</span><span class="br0">)</span> <span class="sy1">=</span> <span class="sy3">&</span>Derived<span class="sy4">::</span><span class="me2">f</span><span class="sy4">;</span>
|
||||
<span class="kw4">void</span> <span class="br0">(</span>Base<span class="sy4">::</span><span class="sy2">*</span> bp<span class="br0">)</span><span class="br0">(</span><span class="kw4">int</span><span class="br0">)</span> <span class="sy1">=</span> <span class="kw1">static_cast</span><span class="sy1"><</span><span class="kw4">void</span> <span class="br0">(</span>Base<span class="sy4">::</span><span class="sy2">*</span><span class="br0">)</span><span class="br0">(</span><span class="kw4">int</span><span class="br0">)</span><span class="sy1">></span><span class="br0">(</span>dp<span class="br0">)</span><span class="sy4">;</span>
|
||||
|
||||
Derived d<span class="sy4">;</span>
|
||||
<span class="br0">(</span>d.<span class="sy2">*</span>bp<span class="br0">)</span><span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// OK:打印 1</span>
|
||||
|
||||
Base b<span class="sy4">;</span>
|
||||
<span class="br0">(</span>b.<span class="sy2">*</span>bp<span class="br0">)</span><span class="br0">(</span><span class="nu0">2</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 未定义行为</span>
|
||||
<span class="br0">}</span></pre></div>
|
||||
</div>
|
||||
<p>成员函数指针可用作回调或函数对象,通常在应用 <span class="t-lc"><a href="cpp-utility-functional-mem_fn.html">std::mem_fn</a></span> 或 <span class="t-lc"><a href="cpp-utility-functional-bind.html">std::bind</a></span> 之后:</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 <iostream></span>
|
||||
<span class="co2">#include <string></span>
|
||||
<span class="co2">#include <algorithm></span>
|
||||
<span class="co2">#include <functional></span>
|
||||
|
||||
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span>
|
||||
<span class="br0">{</span>
|
||||
<a href="cpp-container-vector.html"><span class="kw1269">std::<span class="me2">vector</span></span></a><span class="sy1"><</span><a href="cpp-string-basic_string.html"><span class="kw1230">std::<span class="me2">string</span></span></a><span class="sy1">></span> v <span class="sy1">=</span> <span class="br0">{</span><span class="st0">"a"</span>, <span class="st0">"ab"</span>, <span class="st0">"abc"</span><span class="br0">}</span><span class="sy4">;</span>
|
||||
<a href="cpp-container-vector.html"><span class="kw1269">std::<span class="me2">vector</span></span></a><span class="sy1"><</span><a href="cpp-types-size_t.html"><span class="kw100">std::<span class="me2">size_t</span></span></a><span class="sy1">></span> l<span class="sy4">;</span>
|
||||
transform<span class="br0">(</span>v.<span class="me1">begin</span><span class="br0">(</span><span class="br0">)</span>, v.<span class="me1">end</span><span class="br0">(</span><span class="br0">)</span>, <a href="cpp-iterator-back_inserter.html"><span class="kw665">std::<span class="me2">back_inserter</span></span></a><span class="br0">(</span>l<span class="br0">)</span>,
|
||||
<a href="cpp-utility-functional-mem_fn.html"><span class="kw1057">std::<span class="me2">mem_fn</span></span></a><span class="br0">(</span><span class="sy3">&</span>std<span class="sy4">::</span><span class="me2">string</span><span class="sy4">::</span><span class="me2">size</span><span class="br0">)</span><span class="br0">)</span><span class="sy4">;</span>
|
||||
<span class="kw1">for</span><span class="br0">(</span><a href="cpp-types-size_t.html"><span class="kw100">std::<span class="me2">size_t</span></span></a> n <span class="sy4">:</span> l<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> n <span class="sy1"><<</span> <span class="st0">' '</span><span class="sy4">;</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">1 2 3</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<h3><span class="mw-headline" id=".E7.A9.BA.E6.8C.87.E9.92.88">空指针</span></h3>
|
||||
<p>每个类型的指针都拥有一个特殊值,称为该类型的<i>空指针值(null pointer value)</i>。值为空的指针不指向对象或函数(解引用空指针是未定义行为),并与所有值同样为<i>空</i>的同类型指针比较相等。</p>
|
||||
<p>为将指针初始化为空或赋空值给既存指针,可以使用空指针字面量 <span class="t-c"><span class="mw-geshi cpp source-cpp">nullptr</span></span>、空指针常量 <span class="t-lc"><a href="cpp-types-NULL.html">NULL</a></span> 或从整数值 <span class="t-c"><span class="mw-geshi cpp source-cpp">​<span class="nu0">0</span>​</span></span> 的<a href="cpp-language-implicit_conversion.html">隐式转换</a>。</p>
|
||||
<p><a href="cpp-language-zero_initialization.html">零初始化</a>和<a href="cpp-language-value_initialization.html">值初始化</a>也初始化指针为其空值。</p>
|
||||
<p>空指针可用于指示对象不存在(例如 <a href="cpp-utility-functional-function-target.html"><tt>function::target()</tt></a>),或作为其他错误条件的指示器(例如 <a href="cpp-language-dynamic_cast.html">dynamic_cast</a>)。通常,接受指针实参的函数始终需要检查值是否为空,并以不同方式处理该情况(例如,<a href="cpp-language-delete.html">delete 表达式</a>在传递空指针时不做任何事)。</p>
|
||||
<h3><span class="mw-headline" id=".E5.B8.B8.E9.87.8F.E6.80.A7">常量性</span></h3>
|
||||
<ul>
|
||||
<li>如果指针声明中 <span class="t-spar">限定符</span> 在 <code><b>*</b></code> 之前出现,则它是 <span class="t-spar">声明说明符序列</span> 的一部分,并应用到被指向的对象。</li>
|
||||
<li>若指针声明中 <span class="t-spar">限定符</span> 在 <code><b>*</b></code> 之后出现,则它是 <span class="t-spar">声明符</span> 的一部分,并应用到所声明的指针。</li>
|
||||
</ul>
|
||||
<table class="wikitable">
|
||||
<tr>
|
||||
<th>语法</th>
|
||||
<th>含义</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">const</span> T<span class="sy2">*</span></span></span></td>
|
||||
<td>指向 const 对象的指针</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">T <span class="kw4">const</span><span class="sy2">*</span></span></span></td>
|
||||
<td>指向 const 对象的指针</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">T<span class="sy2">*</span> <span class="kw4">const</span></span></span></td>
|
||||
<td>指向对象的 const 指针</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">const</span> T<span class="sy2">*</span> <span class="kw4">const</span></span></span></td>
|
||||
<td>指向 const 对象的 const 指针</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="t-c"><span class="mw-geshi cpp source-cpp">T <span class="kw4">const</span><span class="sy2">*</span> <span class="kw4">const</span></span></span></td>
|
||||
<td>指向 const 对象的 const 指针</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="co1">// pc 是一个指向 const int 的非 const 指针</span>
|
||||
<span class="co1">// cpc 是一个指向 const int 的 const 指针</span>
|
||||
<span class="co1">// ppc 是一个指向【一个指向 const int 的非 const 指针】的非 const 指针</span>
|
||||
<span class="kw4">const</span> <span class="kw4">int</span> ci <span class="sy1">=</span> <span class="nu0">10</span>, <span class="sy2">*</span>pc <span class="sy1">=</span> <span class="sy3">&</span>ci, <span class="sy2">*</span><span class="kw4">const</span> cpc <span class="sy1">=</span> pc, <span class="sy2">**</span>ppc<span class="sy4">;</span>
|
||||
<span class="co1">// p 是一个指向非 const int 的非 const 指针</span>
|
||||
<span class="co1">// cp 是一个指向非 const int 的 const 指针</span>
|
||||
<span class="kw4">int</span> i, <span class="sy2">*</span>p, <span class="sy2">*</span><span class="kw4">const</span> cp <span class="sy1">=</span> <span class="sy3">&</span>i<span class="sy4">;</span>
|
||||
|
||||
i <span class="sy1">=</span> ci<span class="sy4">;</span> <span class="co1">// OK:复制 const int 值到非 const int</span>
|
||||
<span class="sy2">*</span>cp <span class="sy1">=</span> ci<span class="sy4">;</span> <span class="co1">// OK:能(通过 const 指针)修改非 const int</span>
|
||||
pc<span class="sy2">++</span><span class="sy4">;</span> <span class="co1">// OK:能修改非 const 指针(指向 const int)</span>
|
||||
pc <span class="sy1">=</span> cpc<span class="sy4">;</span> <span class="co1">// OK:能修改非 const 指针(指向 const int)</span>
|
||||
pc <span class="sy1">=</span> p<span class="sy4">;</span> <span class="co1">// OK:能修改非 const 指针(指向 const int)</span>
|
||||
ppc <span class="sy1">=</span> <span class="sy3">&</span>pc<span class="sy4">;</span> <span class="co1">// OK:const int 的指针的地址是 const int 的指针的指针</span>
|
||||
|
||||
ci <span class="sy1">=</span> <span class="nu0">1</span><span class="sy4">;</span> <span class="co1">// 错误:不能修改 const int</span>
|
||||
ci<span class="sy2">++</span><span class="sy4">;</span> <span class="co1">// 错误:不能修改 const int</span>
|
||||
<span class="sy2">*</span>pc <span class="sy1">=</span> <span class="nu0">2</span><span class="sy4">;</span> <span class="co1">// 错误:不能修改被指向的 const int</span>
|
||||
cp <span class="sy1">=</span> <span class="sy3">&</span>ci<span class="sy4">;</span> <span class="co1">// 错误:不能修改 const 指针(指向非 const int)</span>
|
||||
cpc<span class="sy2">++</span><span class="sy4">;</span> <span class="co1">// 错误:不能修改 const 指针(指向 const int)</span>
|
||||
p <span class="sy1">=</span> pc<span class="sy4">;</span> <span class="co1">// 错误:非 const int 的指针不能指向 const int</span>
|
||||
ppc <span class="sy1">=</span> <span class="sy3">&</span>p<span class="sy4">;</span> <span class="co1">// 错误:const int 的指针的指针不能指向非 const int 的指针</span></pre></div>
|
||||
</div>
|
||||
<p>通常,从一个多级指针到另一个的隐式转换遵循<a href="cpp-language-implicit_conversion.html#.E9.99.90.E5.AE.9A.E8.BD.AC.E6.8D.A2">限定转换</a>和<a href="cpp-language-operator_comparison.html#.E6.8C.87.E9.92.88.E6.AF.94.E8.BE.83.E8.BF.90.E7.AE.97.E7.AC.A6">指针比较运算符</a>中所描述的规则。</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/issue73">CWG 73</a></td>
|
||||
<td>C++98</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"></table>
|
||||
</div>
|
||||
<div class="visualClear"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user