测试转载

本文介绍 C++11 中新增的 auto 关键字,解释如何使用 auto 来简化变量类型声明,并探讨其在不同场景下的应用,如初始化、引用、循环等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<div id="article_content" class="article_content csdn-tracking-statistics tracking-click" data-mod="popu_519" data-dsm="post">

                            <div class="markdown_views">
                        <p></p><center> <br>
<font color="#0000FF" size="4" face="黑体"> 本系列文章由</font> <font color="#FF0000" size="4" face="Consolas">@yhl_leo </font><font color="#0000FF" size="4" face="黑体">出品,转载请注明出处。</font> <br>
<font color="#D02090" size="4" face="黑体">文章链接:</font> <font size="4" face="Consolas"> <a href="http://blog.youkuaiyun.com/yhl_leo/article/details/50864612" target="_blank">http://blog.youkuaiyun.com/yhl_leo/article/details/50864612</a></font> <br>
</center><p></p>


<hr>


<p>编程时常常需要把表达式的值赋给变量,这就要求在声明变量的时候清楚知道表达式的类型。然而要做到这一点并非那么容易,有时候甚至根本做不到。为了解决这个问题,C++11标准引入了<code>auto</code>类型说明符,用它就能让编译器替我们去分析表达式所属的类型。</p>


<p>与原来那些只对应一种特定类型的说明符不同,<code>auto</code>让编译器通过初值来推算变量类型。显然,<strong><code>auto</code>定义的变量必须要有初始值。</strong></p>


<p>使用<code>auto</code>具有以下几点好处:</p>


<ul>
<li><strong>可靠性</strong>:如果表达式的类型发生更改(包括函数返回值发生更改的情况),它也能工作。</li>
<li><strong>性能</strong>:确保将不会进行转换。</li>
<li><strong>可用性</strong>:不必担心类型名称拼写困难和拼写有误。</li>
<li><strong>效率</strong>:代码会变得更高效。</li>
</ul>


<pre class="prettyprint"><code class="language-c hljs  has-numbering"><span class="hljs-keyword">auto</span> item = val1 + val2; <span class="hljs-comment">// 由val1和val2相加的结果推断出item的类型</span>


<span class="hljs-keyword">auto</span> i=<span class="hljs-number">0</span>, *p = &amp;i; <span class="hljs-comment">// i是整数,p是整型指针</span></code><ul class="pre-numbering"><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li></ul></pre>


<p>使用<code>auto</code>能在一条语句中声明多个变量。但是一条声明语句只能有一个基本数据类型,所以该语句中所有变量的初始基本数据类型都必须一致:</p>






<pre class="prettyprint"><code class="language-c hljs  has-numbering"><span class="hljs-keyword">auto</span> sz = <span class="hljs-number">0</span>, pi = <span class="hljs-number">3.14</span>; <span class="hljs-comment">// Error!</span></code><ul class="pre-numbering"><li style="color: rgb(153, 153, 153);">1</li></ul></pre>


<p>编译器推断出的<code>auto</code>类型有时候和初始值的类型并不完全一样,编译器会适当地改变结果类型使其更符合初始化规则,例如:</p>


<ul>
<li>使用<code>auto</code>会删除引用</li>
</ul>






<pre class="prettyprint"><code class="language-c hljs  has-numbering"><span class="hljs-keyword">int</span> count = <span class="hljs-number">10</span>;
<span class="hljs-keyword">int</span>&amp; countRef = count;
<span class="hljs-keyword">auto</span> myAuto = countRef;


countRef = <span class="hljs-number">11</span>;
<span class="hljs-built_in">cout</span> &lt;&lt; count &lt;&lt; <span class="hljs-string">" "</span>; <span class="hljs-comment">// print 11</span>


myAuto = <span class="hljs-number">12</span>;
<span class="hljs-built_in">cout</span> &lt;&lt; count &lt;&lt; endl; <span class="hljs-comment">// print 11</span></code><ul class="pre-numbering"><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li></ul></pre>


<p>你可能会认为 <code>myAuto</code> 是一个 <code>int</code> 引用,但它不是。它只是一个 <code>int</code>,因为输出为 <code>11 11</code>,而不是 <code>11 12</code>;如果 <code>auto</code> 尚未删除此引用,则会出现此情况。</p>


<ul>
<li><code>const</code>限定符 <br>
先引入一种表述:<strong>顶层<code>const</code></strong>表示指针本身是个常量,<strong>底层<code>const</code></strong>表示指针所指的对象是一个常量。一般<code>auto</code>会忽略掉顶层<code>const</code>,同时底层<code>const</code>则会保留下来,例如:</li>
</ul>






<pre class="prettyprint"><code class="language-c hljs  has-numbering"><span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>;
<span class="hljs-keyword">const</span> <span class="hljs-keyword">int</span> ci = i, &amp;cr = ci;
<span class="hljs-keyword">auto</span> b = ci;  <span class="hljs-comment">// b 是一个整数(ci的顶层const特性被忽略掉)</span>
<span class="hljs-keyword">auto</span> c = cr;  <span class="hljs-comment">// c 是一个整数(cr是ci的别名,ci本身是一个顶层const)</span>
<span class="hljs-keyword">auto</span> d = &amp;i;  <span class="hljs-comment">// d 是一个整型指针(整数的地址就是指向整数的指针)</span>
<span class="hljs-keyword">auto</span> e = &amp;ci; <span class="hljs-comment">// e 是一个指向整数常量的指针(对常量对象取地址是一种底层const)</span></code><ul class="pre-numbering"><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li></ul></pre>


<p>如果希望推断出的<code>auto</code>类型是一个顶层<code>const</code>,需要明确指出:</p>


<pre class="prettyprint"><code class="language-c hljs  has-numbering"><span class="hljs-keyword">const</span> <span class="hljs-keyword">auto</span> f = ci; <span class="hljs-comment">// ci 的推演类型是int,f是const int类型</span></code><ul class="pre-numbering"><li style="color: rgb(153, 153, 153);">1</li></ul></pre>


<p>还可以将引用的类型设置为<code>auto</code>,此时原来的初始化规则仍然适用:</p>


<pre class="prettyprint"><code class="language-c hljs  has-numbering"><span class="hljs-keyword">auto</span> &amp;g = ci; <span class="hljs-comment">// g是一个整型常量引用,绑定到ci</span>
<span class="hljs-keyword">auto</span> &amp;h = <span class="hljs-number">42</span>; <span class="hljs-comment">// Error: 不能为非常量引用绑定字面值</span>
<span class="hljs-keyword">const</span> <span class="hljs-keyword">auto</span> &amp;j = <span class="hljs-number">42</span>; <span class="hljs-comment">// OK: 可以为常量引用绑定字面值</span></code><ul class="pre-numbering"><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li></ul></pre>


<p>切记,符号<code>*</code>和<code>&amp;</code>只从属于某个声明,而非基本数据类型的一部分,因此初始值必须是同一类型:</p>


<pre class="prettyprint"><code class="language-c hljs  has-numbering"><span class="hljs-keyword">auto</span> k = ci, &amp;l = i; <span class="hljs-comment">// k是整数,l是整型引用</span>
<span class="hljs-keyword">auto</span> &amp;m = ci, *p = &amp;ci; <span class="hljs-comment">// m是对整型常量的引用,p是指向整型常量的指针</span>
<span class="hljs-keyword">auto</span> &amp;n = i, *p2 = &amp;ci; <span class="hljs-comment">// Error: i的类型是int,而&amp;ci的类型是const int</span></code><ul class="pre-numbering"><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li></ul></pre>


<p>附上更多示例代码:</p>


<ul>
<li>下面的声明等效。在第一个语句中,将变量<code>j</code> 声明为类型 <code>int</code>。在第二个语句中,将变量 <code>k</code> 推导为类型 <code>int</code>,因为初始化表达式 (0) 是整数</li>
</ul>


<pre class="prettyprint"><code class="language-c hljs  has-numbering"><span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>;  <span class="hljs-comment">// Variable j is explicitly type int.</span>
<span class="hljs-keyword">auto</span> k = <span class="hljs-number">0</span>; <span class="hljs-comment">// Variable k is implicitly type int because 0 is an integer.</span></code><ul class="pre-numbering"><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre>


<ul>
<li>以下声明等效,但第二个声明比第一个更简单。使用 <code>auto</code> 关键字的最令人信服的一个原因是简单</li>
</ul>


<pre class="prettyprint"><code class="language-c hljs  has-numbering"><span class="hljs-stl_container"><span class="hljs-built_in">map</span>&lt;<span class="hljs-keyword">int</span>,<span class="hljs-stl_container"><span class="hljs-built_in">list</span>&lt;<span class="hljs-built_in">string</span>&gt;</span>&gt;</span>::iterator i = m.begin(); 
<span class="hljs-keyword">auto</span> i = m.begin(); </code><ul class="pre-numbering"><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre>


<ul>
<li>使用 <code>iter</code> 和 <code>elem</code> 启动循环时</li>
</ul>


<pre class="prettyprint"><code class="language-c hljs  has-numbering"><span class="hljs-preprocessor">#include &lt;deque&gt;</span>
<span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> <span class="hljs-built_in">std</span>;


<span class="hljs-keyword">int</span> main()
{
    <span class="hljs-stl_container"><span class="hljs-built_in">deque</span>&lt;<span class="hljs-keyword">double</span>&gt;</span> dqDoubleData(<span class="hljs-number">10</span>, <span class="hljs-number">0.1</span>);


    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">auto</span> iter = dqDoubleData.begin(); iter != dqDoubleData.end(); ++iter)
    { <span class="hljs-comment">/* ... */</span> }


    <span class="hljs-comment">// prefer range-for loops with the following information in mind</span>
    <span class="hljs-comment">// (this applies to any range-for with auto, not just deque)</span>


    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">auto</span> elem : dqDoubleData) <span class="hljs-comment">// COPIES elements, not much better than the previous examples</span>
    { <span class="hljs-comment">/* ... */</span> }


    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">auto</span>&amp; elem : dqDoubleData) <span class="hljs-comment">// observes and/or modifies elements IN-PLACE</span>
    { <span class="hljs-comment">/* ... */</span> }


    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> <span class="hljs-keyword">auto</span>&amp; elem : dqDoubleData) <span class="hljs-comment">// observes elements IN-PLACE</span>
    { <span class="hljs-comment">/* ... */</span> }
}</code><ul class="pre-numbering"><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li></ul></pre>


<ul>
<li>下面的代码片段使用 <code>new</code> 运算符和指针声明来声明指针</li>
</ul>






<pre class="prettyprint"><code class="language-c hljs  has-numbering"><span class="hljs-keyword">double</span> x = <span class="hljs-number">12.34</span>;
<span class="hljs-keyword">auto</span> *y = <span class="hljs-keyword">new</span> <span class="hljs-keyword">auto</span>(x), **z = <span class="hljs-keyword">new</span> <span class="hljs-keyword">auto</span>(&amp;x);</code><ul class="pre-numbering"><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre>


<ul>
<li>下一个代码片段在每个声明语句中声明多个符号。请注意,每个语句中的所有符号将解析为同一类型。</li>
</ul>






<pre class="prettyprint"><code class="language-c hljs  has-numbering"><span class="hljs-keyword">auto</span> x = <span class="hljs-number">1</span>, *y = &amp;x, **z = &amp;y; <span class="hljs-comment">// Resolves to int.</span>
<span class="hljs-keyword">auto</span> a(<span class="hljs-number">2.01</span>), *b (&amp;a);         <span class="hljs-comment">// Resolves to double.</span>
<span class="hljs-keyword">auto</span> c = <span class="hljs-string">'a'</span>, *d(&amp;c);          <span class="hljs-comment">// Resolves to char.</span>
<span class="hljs-keyword">auto</span> m = <span class="hljs-number">1</span>, &amp;n = m;            <span class="hljs-comment">// Resolves to int.</span></code><ul class="pre-numbering"><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li></ul></pre>


<ul>
<li>此代码片段使用条件运算符 (<code>?:</code>) 将变量 <code>x</code> 声明为值为 <code>200</code> 的整数:</li>
</ul>


<pre class="prettyprint"><code class="language-c hljs  has-numbering"><span class="hljs-keyword">int</span> v1 = <span class="hljs-number">100</span>, v2 = <span class="hljs-number">200</span>;
<span class="hljs-keyword">auto</span> x = v1 &gt; v2 ? v1 : v2;</code><ul class="pre-numbering"><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre>


<ul>
<li>下面的代码片段将变量 <code>x</code> 初始化为类型 <code>int</code>,将变量 <code>y</code>初始化对类型 <code>const int</code> 的引用,将变量 <code>fp</code> 初始化为指向返回类型 <code>int</code> 的函数的指针。</li>
</ul>


<pre class="prettyprint"><code class="language-c hljs  has-numbering"><span class="hljs-keyword">int</span> f(<span class="hljs-keyword">int</span> x) { <span class="hljs-keyword">return</span> x; }
<span class="hljs-keyword">int</span> main()
{
    <span class="hljs-keyword">auto</span> x = f(<span class="hljs-number">0</span>);
    <span class="hljs-keyword">const</span> <span class="hljs-keyword">auto</span> &amp; y = f(<span class="hljs-number">1</span>);
    <span class="hljs-keyword">int</span> (*p)(<span class="hljs-keyword">int</span> x);
    p = f;
    <span class="hljs-keyword">auto</span> fp = p;
    <span class="hljs-comment">//...</span>
}</code><ul class="pre-numbering"><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li></ul></pre>


<p><span class="MathJax_Preview" style="color: inherit; display: none;"></span><span class="MathJax" id="MathJax-Element-28-Frame" tabindex="0" data-mathml="<math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; />" role="presentation" style="position: relative;"><nobr aria-hidden="true"><span class="math" id="MathJax-Span-1" style="width: 0em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0em; height: 0px; font-size: 130%;"><span style="position: absolute; clip: rect(3.849em 1000em 4.137em -999.998em); top: -3.988em; left: 0em;"><span class="mrow" id="MathJax-Span-2"></span><span style="display: inline-block; width: 0px; height: 3.993em;"></span></span></span><span style="display: inline-block; overflow: hidden; vertical-align: -0.059em; border-left: 0px solid; width: 0px; height: 0.128em;"></span></span></nobr><span class="MJX_Assistive_MathML" role="presentation"><math xmlns="http://www.w3.org/1998/Math/MathML"></math></span></span><script type="math/tex" id="MathJax-Element-28"> </script></p>


<p>参考:</p>


<ul>
<li><a href="https://msdn.microsoft.com/zh-cn/library/dd293667.aspx" target="_blank">Microsoft Developer Network: auto(C++)</a></li>
<li>《C++ Primer(第五版)》 Stanley B. Lippman.</li>
</ul>                </div>
                                                <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/production/markdown_views-ea0013b516.css">
                                    </div>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值