上传cppreference
This commit is contained in:
169
web/cppreference-zh/chmhelp/cpp-language-cv.html
Normal file
169
web/cppreference-zh/chmhelp/cpp-language-cv.html
Normal file
@@ -0,0 +1,169 @@
|
||||
<!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>cv(const 与 volatile)类型限定符</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_cv skin-cppreference2 action-view cpp-navbar">
|
||||
<div id="cpp-content-base">
|
||||
<div id="content"><a id="top"></a>
|
||||
<h1 id="firstHeading" class="firstHeading">cv(<span style="font-size:0.7em; line-height:130%">const</span> 与 <span style="font-size:0.7em; line-height:130%">volatile</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>可出现于任何类型说明符(包括<a href="cpp-language-declarations.html">声明文法</a>的 <span class="t-spar">声明说明符序列</span>)中,以指定被声明对象或被命名类型的常量性(constness)或易变性(volatility)。</p>
|
||||
<dl>
|
||||
<dd>
|
||||
<ul>
|
||||
<li><code><b>const</b></code> ——定义类型为<i>常量</i>。</li>
|
||||
<li><code><b>volatile</b></code> ——定义类型为<i>易变</i>。</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3><span class="mw-headline" id=".E8.A7.A3.E9.87.8A">解释</span></h3>
|
||||
<p>对于除了<a href="cpp-language-functions.html">函数类型</a>或<a href="cpp-language-reference.html">引用类型</a>以外的任何类型 <code>T</code>(包括不完整类型),C++ 类型系统中有另外三个独立的类型:<span class="t-spar">const-限定的</span> <code>T</code>、<span class="t-spar">volatile-限定的</span> <code>T</code> 及 <span class="t-spar">const-volatile-限定的</span> <code>T</code>。</p>
|
||||
<dl>
|
||||
<dd>注意:<a href="cpp-language-array.html">数组类型</a>被当做与其元素类型有相同的 cv 限定。</dd>
|
||||
</dl>
|
||||
<p>当对象最初被创建时,所用的 cv 限定符(可以是<a href="cpp-language-declarations.html">声明</a>中的 <span class="t-spar">声明说明符序列</span> 或 <span class="t-spar">声明符</span> 的一部分,或者是 <a href="cpp-language-new.html">new 表达式</a>中的 <span class="t-spar">类型标识</span> 的一部分)决定对象的常量性或易变性,如下所示:</p>
|
||||
<ul>
|
||||
<li><i><b>const 对象</b></i>——类型为 <span class="t-spar">const-限定的</span> 对象,或 const 对象的非 mutable 子对象。这种对象不能被修改:直接尝试这么做是编译时错误,而间接尝试这么做(例如通过到非 const 类型的引用或指针修改 const 对象)会导致未定义行为。</li>
|
||||
<li><i><b>volatile 对象</b></i>——类型为 <span class="t-spar">volatile-限定的</span> 对象,或 volatile 对象的子对象,或 const volatile 对象的 mutable 子对象。通过 volatile 限定的类型的泛左值表达式的每次访问(读或写操作、成员函数调用等),都被当作对于<a href="cpp-language-as_if.html">优化</a>而言是可见的副作用(即在单个执行线程内,volatile 访问不能被优化掉,或者与另一<a href="cpp-language-eval_order.html">按顺序早于</a>或按顺序晚于该 volatile 访问的可见副作用进行重排序。这使得 volatile 对象适用于与<a href="cpp-utility-program-signal.html">信号处理函数</a>之间的交流,但不适于与另一执行线程交流,参阅 <span class="t-lc"><a href="cpp-atomic-memory_order.html">std::memory_order</a></span>)。试图通过非 volatile 类型的<a href="cpp-language-value_category.html#.E6.B3.9B.E5.B7.A6.E5.80.BC">泛左值</a>涉指 volatile 对象(例如,通过到非 volatile 类型的引用或指针)会导致未定义行为。</li>
|
||||
<li><i><b>const volatile 对象</b></i>——类型为 <span class="t-spar">const-volatile-限定的</span> 对象,const volatile 对象的非 mutable 子对象,volatile 对象的 const 子对象,或 const 对象的非 mutable volatile 子对象。同时表现为 const 对象与 volatile 对象。</li>
|
||||
</ul>
|
||||
<h3><span class="mw-headline" id="mutable_.E8.AF.B4.E6.98.8E.E7.AC.A6"><span class="t-lc">mutable</span> 说明符</span></h3>
|
||||
<dl>
|
||||
<dd>
|
||||
<ul>
|
||||
<li><code><b>mutable</b></code> - 容许在即便包含它的对象被声明为 const 时仍可修改声明为 mutable 的类成员。</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
<p>可出现于非引用非 const 类型的非静态<a href="cpp-language-data_members.html">数据成员</a>的声明中:</p>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="kw1">class</span> X <span class="br0">{</span>
|
||||
mutable <span class="kw4">const</span> <span class="kw4">int</span><span class="sy2">*</span> p<span class="sy4">;</span> <span class="co1">// OK</span>
|
||||
mutable <span class="kw4">int</span><span class="sy2">*</span> <span class="kw4">const</span> q<span class="sy4">;</span> <span class="co1">// 非良构</span>
|
||||
<span class="br0">}</span><span class="sy4">;</span></pre></div>
|
||||
</div>
|
||||
<p>mutable 用于指定不影响类的外部可观察状态的成员(通常用于互斥体、记忆缓存、惰性求值和访问指令等)。</p>
|
||||
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
||||
<div class="cpp source-cpp">
|
||||
<pre class="de1"><span class="kw1">class</span> ThreadsafeCounter <span class="br0">{</span>
|
||||
mutable <a href="cpp-thread-mutex.html"><span class="kw2154">std::<span class="me2">mutex</span></span></a> m<span class="sy4">;</span> <span class="co1">// “M&M 规则”:mutable 与 mutex 一起出现</span>
|
||||
<span class="kw4">int</span> data <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span>
|
||||
<span class="kw1">public</span><span class="sy4">:</span>
|
||||
<span class="kw4">int</span> get<span class="br0">(</span><span class="br0">)</span> <span class="kw4">const</span> <span class="br0">{</span>
|
||||
<a href="cpp-thread-lock_guard.html"><span class="kw2166">std::<span class="me2">lock_guard</span></span></a><span class="sy1"><</span><a href="cpp-thread-mutex.html"><span class="kw2154">std::<span class="me2">mutex</span></span></a><span class="sy1">></span> lk<span class="br0">(</span>m<span class="br0">)</span><span class="sy4">;</span>
|
||||
<span class="kw1">return</span> data<span class="sy4">;</span>
|
||||
<span class="br0">}</span>
|
||||
<span class="kw4">void</span> inc<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
|
||||
<a href="cpp-thread-lock_guard.html"><span class="kw2166">std::<span class="me2">lock_guard</span></span></a><span class="sy1"><</span><a href="cpp-thread-mutex.html"><span class="kw2154">std::<span class="me2">mutex</span></span></a><span class="sy1">></span> lk<span class="br0">(</span>m<span class="br0">)</span><span class="sy4">;</span>
|
||||
<span class="sy2">++</span>data<span class="sy4">;</span>
|
||||
<span class="br0">}</span>
|
||||
<span class="br0">}</span><span class="sy4">;</span></pre></div>
|
||||
</div>
|
||||
<h3><span class="mw-headline" id=".E8.BD.AC.E6.8D.A2">转换</span></h3>
|
||||
<p>存在一种基于限制性的增长顺序的 cv 限定符的偏序。从而可以称类型具有<i>更多</i>或<i>更少</i>的 cv 限定:</p>
|
||||
<dl>
|
||||
<dd>
|
||||
<ul>
|
||||
<li><i>无限定</i> < <code>const</code></li>
|
||||
<li><i>无限定</i> < <code>volatile</code></li>
|
||||
<li><i>无限定</i> < <code>const volatile</code></li>
|
||||
<li><code>const</code> < <code>const volatile</code></li>
|
||||
<li><code>volatile</code> < <code>const volatile</code></li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
<p>到 cv 限定类型的引用和指针能被<a href="cpp-language-implicit_conversion.html#.E9.99.90.E5.AE.9A.E8.BD.AC.E6.8D.A2">隐式转换</a>到<i>更多 cv 限定</i>的类型的引用和指针。特别是允许下列转换:</p>
|
||||
<dl>
|
||||
<dd>
|
||||
<ul>
|
||||
<li>到<i>无限定</i>类型的引用/指针能被转换成到 <code>const</code> 的引用/指针</li>
|
||||
<li>到<i>无限定</i>类型的引用/指针能被转换成到 <code>volatile</code> 的引用/指针</li>
|
||||
<li>到<i>无限定</i>类型的引用/指针能被转换成到 <code>const volatile</code> 的引用/指针</li>
|
||||
<li>到 <code>const</code> 类型的引用/指针能被转换成到 <code>const volatile</code> 的引用/指针</li>
|
||||
<li>到 <code>volatile</code> 类型的引用/指针能被转换成到 <code>const volatile</code> 的引用/指针</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dd>注意:多级指针另有<a href="cpp-language-implicit_conversion.html#.E9.99.90.E5.AE.9A.E8.BD.AC.E6.8D.A2">其他限制</a>。</dd>
|
||||
</dl>
|
||||
<p>想要将到 cv 限定类型的引用或指针转换为到<i>更少 cv 限定</i>类型的引用或指针就必须使用 <a href="cpp-language-const_cast.html">const_cast</a>。</p>
|
||||
<h3><span class="mw-headline" id=".E5.85.B3.E9.94.AE.E8.AF.8D">关键词</span></h3>
|
||||
<p><a href="cpp-keyword-const.html"><tt>const</tt></a>, <a href="cpp-keyword-volatile.html"><tt>volatile</tt></a>, <a href="cpp-keyword-mutable.html"><tt>mutable</tt></a></p>
|
||||
<h3><span class="mw-headline" id=".E6.B3.A8.E8.A7.A3">注解</span></h3>
|
||||
<p>在未声明为 <code>extern</code> 的非局部非 volatile <span class="t-rev-inl t-since-cxx14"><span>非<a href="cpp-language-variable_template.html">模板</a></span> <span><span class="t-mark-rev t-since-cxx14">(C++14 起)</span></span></span><span class="t-rev-inl t-since-cxx17"><span>非 <a href="cpp-language-inline.html">inline</a></span> <span><span class="t-mark-rev t-since-cxx17">(C++17 起)</span></span></span>变量声明上使用 <code>const</code> 限定符,会给予该变量<a href="cpp-language-storage_duration.html#.E8.BF.9E.E6.8E.A5">内部连接</a>。这有别于 C,其中 const 文件作用域对象拥有外部连接。</p>
|
||||
<p>C++ 语言文法把 <code>mutable</code> 当做<a href="cpp-language-storage_duration.html">存储类说明符</a>而非类型限定符,但它不影响存储类或连接。</p>
|
||||
<table class="t-rev-begin">
|
||||
<tr class="t-rev t-since-cxx20">
|
||||
<td>
|
||||
<p>volatile 的一些用法被弃用:</p>
|
||||
<ul>
|
||||
<li>volatile 类型的左值作为内建<a href="cpp-language-operator_incdec.html">自增/自减</a>运算符的操作数;</li>
|
||||
<li>volatile 类型的左值作为内建<a href="cpp-language-operator_assignment.html">直接/复合赋值</a>运算符的左操作数,除非该直接赋值表达式出现于<a href="cpp-language-expressions.html#.E4.B8.8D.E6.B1.82.E5.80.BC.E8.A1.A8.E8.BE.BE.E5.BC.8F">不求值语境</a>或是<a href="cpp-language-expressions.html#.E5.BC.83.E5.80.BC.E8.A1.A8.E8.BE.BE.E5.BC.8F">弃值表达式</a>;</li>
|
||||
<li>volatile 对象类型作为函数参数类型或返回类型;</li>
|
||||
<li>volatile 限定符在<a href="cpp-language-structured_binding.html">结构化绑定</a>声明中。</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></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="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span>
|
||||
<span class="br0">{</span>
|
||||
<span class="kw4">int</span> n1 <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span> <span class="co1">// 非 const 对象</span>
|
||||
<span class="kw4">const</span> <span class="kw4">int</span> n2 <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span> <span class="co1">// const 对象</span>
|
||||
<span class="kw4">int</span> <span class="kw4">const</span> n3 <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span> <span class="co1">// const 对象(同 n2)</span>
|
||||
<span class="kw4">volatile</span> <span class="kw4">int</span> n4 <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span> <span class="co1">// volatile 对象</span>
|
||||
<span class="kw4">const</span> <span class="kw1">struct</span>
|
||||
<span class="br0">{</span>
|
||||
<span class="kw4">int</span> n1<span class="sy4">;</span>
|
||||
mutable <span class="kw4">int</span> n2<span class="sy4">;</span>
|
||||
<span class="br0">}</span> x <span class="sy1">=</span> <span class="br0">{</span><span class="nu0">0</span>, <span class="nu0">0</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// 带 mutable 成员的 const 对象</span>
|
||||
|
||||
n1 <span class="sy1">=</span> <span class="nu0">1</span><span class="sy4">;</span> <span class="co1">// OK,可修改对象</span>
|
||||
<span class="co1">// n2 = 2; // 错误:不可修改对象</span>
|
||||
n4 <span class="sy1">=</span> <span class="nu0">3</span><span class="sy4">;</span> <span class="co1">// OK,当做副作用</span>
|
||||
<span class="co1">// x.n1 = 4; // 错误:const 对象的成员为 const</span>
|
||||
x.<span class="me1">n2</span> <span class="sy1">=</span> <span class="nu0">4</span><span class="sy4">;</span> <span class="co1">// OK,const 对象的 mutable 成员不是 const</span>
|
||||
|
||||
<span class="kw4">const</span> <span class="kw4">int</span><span class="sy3">&</span> r1 <span class="sy1">=</span> n1<span class="sy4">;</span> <span class="co1">// 绑定到非 const 对象的 const 引用</span>
|
||||
<span class="co1">// r1 = 2; // 错误:试图通过到 const 的引用修改</span>
|
||||
<span class="kw1">const_cast</span><span class="sy1"><</span><span class="kw4">int</span><span class="sy3">&</span><span class="sy1">></span><span class="br0">(</span>r1<span class="br0">)</span> <span class="sy1">=</span> <span class="nu0">2</span><span class="sy4">;</span> <span class="co1">// OK,修改非 const 对象 n1</span>
|
||||
|
||||
<span class="kw4">const</span> <span class="kw4">int</span><span class="sy3">&</span> r2 <span class="sy1">=</span> n2<span class="sy4">;</span> <span class="co1">// 绑定到 const 对象的 const 引用</span>
|
||||
<span class="co1">// r2 = 2; // 错误:试图通过到 const 的引用修改</span>
|
||||
<span class="co1">// const_cast<int&>(r2) = 2; // 未定义行为:试图修改 const 对象 n2</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"># x86_64 平台上生成的典型机器码
|
||||
# (只输出贡献可观测副效应的代码)
|
||||
main:
|
||||
movl $0, -4(%rsp) # volatile int n4 = 0;
|
||||
movl $3, -4(%rsp) # n4 = 3;
|
||||
xorl %eax, %eax # return 0 (隐式)
|
||||
ret</pre></div>
|
||||
</div>
|
||||
</div>
|
||||
<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