You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1644 lines
225 KiB
HTML
1644 lines
225 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en" dir="ltr">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="description" content="Chapter 3: A First Impression Of C++ # In this chapter C++ is further explored. The possibility to declare functions in structs is illustrated in various examples; the concept of a class is introduced; casting is covered in detail; many new types are introduced and several important notational extensions to C are discussed.
|
|
3.1: Notable differences with C # Before we continue with the real object-approach to programming, we first introduce some notable differences with the C programming language: not mere differences between C and C++, but important syntactic constructs and keywords not found or differently used in C.">
|
|
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#ffffff">
|
|
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#343a40">
|
|
<meta name="color-scheme" content="light dark"><meta property="og:url" content="https://doc.cyub.vip/cpp/docs/A-First-Impression/">
|
|
<meta property="og:site_name" content="C++ Annotations Version 12.4.0">
|
|
<meta property="og:title" content="C++ Annotations Version 12.4.0">
|
|
<meta property="og:description" content="Chapter 3: A First Impression Of C++ # In this chapter C++ is further explored. The possibility to declare functions in structs is illustrated in various examples; the concept of a class is introduced; casting is covered in detail; many new types are introduced and several important notational extensions to C are discussed.
|
|
3.1: Notable differences with C # Before we continue with the real object-approach to programming, we first introduce some notable differences with the C programming language: not mere differences between C and C++, but important syntactic constructs and keywords not found or differently used in C.">
|
|
<meta property="og:locale" content="en">
|
|
<meta property="og:type" content="article">
|
|
<meta property="article:section" content="docs">
|
|
<title>A First Impression | C++ Annotations Version 12.4.0</title>
|
|
<link rel="manifest" href="/cpp/manifest.json">
|
|
<link rel="icon" href="/cpp/favicon.png" >
|
|
<link rel="canonical" href="https://doc.cyub.vip/cpp/docs/A-First-Impression/">
|
|
<link rel="alternate" hreflang="zh" href="https://doc.cyub.vip/cpp/zh/docs/A-First-Impression/" title="A First Impression">
|
|
<link rel="stylesheet" href="/cpp/book.min.309b7ed028807cdb68d8d61e26d609f48369c098dbf5e4d8c0dcf4cdf49feafc.css" integrity="sha256-MJt+0CiAfNto2NYeJtYJ9INpwJjb9eTYwNz0zfSf6vw=" crossorigin="anonymous">
|
|
<script defer src="/cpp/fuse.min.js"></script>
|
|
<script defer src="/cpp/en.search.min.96d87afe14f4404fb82eb23166af34b971841affca153da6e6aee977701013ac.js" integrity="sha256-lth6/hT0QE+4LrIxZq80uXGEGv/KFT2m5q7pd3AQE6w=" crossorigin="anonymous"></script>
|
|
|
|
<script defer src="/cpp/sw.min.5d1fdbd1fdf1d81d76c1e5a2529d146b38922120c27ebed041d7584fa87ce6df.js" integrity="sha256-XR/b0f3x2B12weWiUp0UaziSISDCfr7QQddYT6h85t8=" crossorigin="anonymous"></script>
|
|
|
|
|
|
|
|
<!--
|
|
Made with Book Theme
|
|
https://github.com/alex-shpak/hugo-book
|
|
-->
|
|
|
|
</head>
|
|
<body dir="ltr">
|
|
<input type="checkbox" class="hidden toggle" id="menu-control" />
|
|
<input type="checkbox" class="hidden toggle" id="toc-control" />
|
|
<main class="container flex">
|
|
<aside class="book-menu">
|
|
<div class="book-menu-content">
|
|
|
|
<nav>
|
|
<h2 class="book-brand">
|
|
<a class="flex align-center" href="/cpp/"><span>C++ Annotations Version 12.4.0</span>
|
|
</a>
|
|
</h2>
|
|
|
|
|
|
<div class="book-search hidden">
|
|
<input type="text" id="book-search-input" placeholder="Search" aria-label="Search" maxlength="64" data-hotkeys="s/" />
|
|
<div class="book-search-spinner hidden"></div>
|
|
<ul id="book-search-results"></ul>
|
|
</div>
|
|
<script>document.querySelector(".book-search").classList.remove("hidden")</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<ul class="book-languages">
|
|
<li>
|
|
<input type="checkbox" id="languages" class="toggle" />
|
|
<label for="languages" class="flex justify-between">
|
|
<a role="button" class="flex align-center">
|
|
<img src="/cpp/svg/translate.svg" class="book-icon" alt="Languages" />
|
|
English
|
|
</a>
|
|
</label>
|
|
|
|
<ul>
|
|
|
|
<li>
|
|
<a href="https://doc.cyub.vip/cpp/zh/docs/A-First-Impression/">
|
|
Chinese
|
|
</a>
|
|
</li>
|
|
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<ul>
|
|
<li>
|
|
<a href="/cpp/docs/Overview/">1. Overview</a></li>
|
|
<li><strong>2. C++ Intro</strong></li>
|
|
<li>
|
|
<a href="/cpp/docs/A-First-Impression/"class=active>3. A First Impression</a></li>
|
|
<li>
|
|
<a href="/cpp/docs/Name-Spaces/">4. Name Spaces</a></li>
|
|
<li><strong>5. Strings</strong></li>
|
|
<li>
|
|
<a href="/cpp/docs/IOStreams/">6. IOStreams</a></li>
|
|
<li><strong>7. Classes</strong></li>
|
|
<li>
|
|
<a href="/cpp/docs/Static-Data-And-Functions/">8. Static Data And Functions</a></li>
|
|
<li><strong>9. Memory Management</strong></li>
|
|
<li><strong>10. Exceptions</strong></li>
|
|
<li><strong>11. Operator Overloading</strong></li>
|
|
<li><strong>12. Abstract Containers</strong></li>
|
|
<li><strong>13. Inheritance</strong></li>
|
|
<li><strong>14. Polymorphism</strong></li>
|
|
<li>
|
|
<a href="/cpp/docs/Friends/">15. Friends</a></li>
|
|
<li><strong>16. Pointers to Members</strong></li>
|
|
<li><strong>17. Nested Classes</strong></li>
|
|
<li><strong>18. Standard Template Library</strong></li>
|
|
<li><strong>19. Generic Algorithms</strong></li>
|
|
<li><strong>20. Multi Threading</strong></li>
|
|
<li><strong>21. Function Templates</strong></li>
|
|
<li><strong>22. Class Templates</strong></li>
|
|
<li><strong>23. Advanced Template Use</strong></li>
|
|
<li><strong>24. Coroutines</strong></li>
|
|
<li><strong>25. Examples</strong></li>
|
|
</ul>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</nav>
|
|
|
|
|
|
|
|
|
|
<script>(function(){var e=document.querySelector("aside .book-menu-content");addEventListener("beforeunload",function(){localStorage.setItem("menu.scrollTop",e.scrollTop)}),e.scrollTop=localStorage.getItem("menu.scrollTop")})()</script>
|
|
|
|
|
|
|
|
</div>
|
|
</aside>
|
|
|
|
<div class="book-page">
|
|
<header class="book-header">
|
|
|
|
<div class="flex align-center justify-between">
|
|
<label for="menu-control">
|
|
<img src="/cpp/svg/menu.svg" class="book-icon" alt="Menu" />
|
|
</label>
|
|
|
|
<strong>A First Impression</strong>
|
|
|
|
<label for="toc-control">
|
|
|
|
</label>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
<article class="markdown book-article"><h1 id="chapter-3-a-first-impression-of-c">
|
|
Chapter 3: A First Impression Of C++
|
|
<a class="anchor" href="#chapter-3-a-first-impression-of-c">#</a>
|
|
</h1>
|
|
<p>In this chapter C++ is further explored. The possibility to declare functions in structs is illustrated in various examples; the concept of a class is introduced; casting is covered in detail; many new types are introduced and several important notational extensions to C are discussed.</p>
|
|
<h2 id="31-notable-differences-with-c">
|
|
3.1: Notable differences with C
|
|
<a class="anchor" href="#31-notable-differences-with-c">#</a>
|
|
</h2>
|
|
<p>Before we continue with the real object-approach to programming, we first introduce some notable differences with the C programming language: not mere differences between C and C++, but important syntactic constructs and keywords not found or differently used in C.</p>
|
|
<h3 id="311-using-the-keyword-const">
|
|
3.1.1: Using the keyword <strong>const</strong>
|
|
<a class="anchor" href="#311-using-the-keyword-const">#</a>
|
|
</h3>
|
|
<p>Even though the keyword <code>const</code> is part of the C grammar, its use is more important and much more common and strictly used in C++ than it is in C.</p>
|
|
<p>The <code>const</code> keyword is a modifier stating that the value of a variable or of an argument may not be modified. In the following example the intent is to change the value of a variable <code>ival</code>, which fails:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> <span style="color:#66d9ef">const</span> ival <span style="color:#f92672">=</span> <span style="color:#ae81ff">3</span>; <span style="color:#75715e">// a constant int
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#75715e">// initialized to 3
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span> ival <span style="color:#f92672">=</span> <span style="color:#ae81ff">4</span>; <span style="color:#75715e">// assignment produces
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#75715e">// an error message
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
|
|
</span></span></code></pre></div><p>This example shows how <code>ival</code> may be initialized to a given value in its definition; attempts to change the value later (in an assignment) are not permitted.</p>
|
|
<p>Variables that are declared <code>const</code> can, in contrast to C, be used to specify the size of an array, as in the following example:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#66d9ef">const</span> size <span style="color:#f92672">=</span> <span style="color:#ae81ff">20</span>;
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">char</span> buf[size]; <span style="color:#75715e">// 20 chars big
|
|
</span></span></span></code></pre></div><p>Another use of the keyword <code>const</code> is seen in the declaration of pointers, e.g., in pointer-arguments. In the declaration</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span>buf;
|
|
</span></span></code></pre></div><p><code>buf</code> is a pointer variable pointing to chars. Whatever is pointed to by buf may not be changed through buf: the chars are declared as const. The pointer buf itself however may be changed. A statement like <code>*buf = 'a'</code>; is therefore not allowed, while <code>++buf</code> is.</p>
|
|
<p>In the declaration</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> buf;
|
|
</span></span></code></pre></div><p>buf itself is a <code>const pointer</code> which may not be changed. Whatever chars are pointed to by buf may be changed at will.</p>
|
|
<p>Finally, the declaration</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> buf;
|
|
</span></span></code></pre></div><p>is also possible; here, neither the pointer nor what it points to may be changed.</p>
|
|
<p>The rule of thumb for the placement of the keyword <code>const</code> is the following: whatever occurs to the left to the keyword may not be changed.</p>
|
|
<p>Although simple, this rule of thumb is often used. For example, Bjarne Stroustrup states (in
|
|
<a href="https://www.stroustrup.com/bs_faq2.html#constplacement">https://www.stroustrup.com/bs_faq2.html#constplacement</a>):</p>
|
|
<blockquote>
|
|
<p>Should I put <code>const</code> before or after the type?</p>
|
|
<p>I put it before, but that’s a matter of taste. <code>const T</code> and <code>T const</code> were always (both) allowed and equivalent. For example:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#66d9ef">int</span> a <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>; <span style="color:#75715e">// OK
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">int</span> <span style="color:#66d9ef">const</span> b <span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span>; <span style="color:#75715e">// also OK
|
|
</span></span></span></code></pre></div><p>My guess is that using the first version will confuse fewer programmers (<code>is more idiomatic</code>).</p>
|
|
</blockquote>
|
|
<p>But we’ve already seen an example where applying this simple <code>before</code> placement rule for the keyword <code>const</code> produces unexpected (i.e., unwanted) results as we will shortly see (below). Furthermore, the <code>idiomatic</code> before-placement also conflicts with the notion of <code>const</code> functions, which we will encounter in section
|
|
<a href="/cpp/">7.7</a>. With const functions the keyword <code>const</code> is also placed behind rather than before the name of the function.</p>
|
|
<p>The definition or declaration (either or not containing <code>const</code>) should always be read from the variable or function identifier back to the type identifier:</p>
|
|
<blockquote>
|
|
<p>Buf is a <strong>const pointer</strong> to <strong>const characters</strong></p>
|
|
</blockquote>
|
|
<p>This rule of thumb is especially useful in cases where confusion may occur. In examples of C++ code published in other places one often encounters the reverse: <code>const</code> preceding what should not be altered. That this may result in sloppy code is indicated by our second example above:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span>buf;
|
|
</span></span></code></pre></div><p>What must remain constant here? According to the sloppy interpretation, the pointer cannot be altered (as <code>const</code> precedes the pointer). In fact, the <code>char</code> values are the constant entities here, as becomes clear when we try to compile the following program:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span>buf <span style="color:#f92672">=</span> <span style="color:#e6db74">"hello"</span>;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672">++</span>buf; <span style="color:#75715e">// accepted by the compiler
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#f92672">*</span>buf <span style="color:#f92672">=</span> <span style="color:#e6db74">'u'</span>; <span style="color:#75715e">// rejected by the compiler
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
|
|
</span></span></code></pre></div><p>Compilation fails on the statement <code>*buf = 'u'</code>; and not on the statement <code>++buf</code>.</p>
|
|
<p>Marshall Cline’s
|
|
<a href="http://www.parashift.com/c++-faq-lite/const-correctness.html">C++ FAQ</a> gives the same rule (paragraph 18.5) , in a similar context:</p>
|
|
<blockquote>
|
|
<p>[18.5] What’s the difference between <strong>const Fred* p</strong>, <strong>Fred* const p</strong> and <strong>const Fred* const p</strong>?</p>
|
|
<p>You have to read pointer declarations right-to-left.</p>
|
|
</blockquote>
|
|
<p>Marshall Cline’s advice can be improved, though. Here’s a recipe that will effortlessly dissect even the most complex declaration:</p>
|
|
<ol>
|
|
<li>start reading at the variable’s name</li>
|
|
<li>read as far as possible until you reach the end of the declaration or an (as yet unmatched) closing parenthesis.</li>
|
|
<li>return to the point where you started reading, and read backwards until you reach the beginning of the declaration or a matching opening parenthesis.</li>
|
|
<li>If you reached an opening parenthesis, continue at step 2 beyond the parenthesis where you previously stopped.</li>
|
|
</ol>
|
|
<p>Let’s apply this recipe to the following (by itself irrelevant) complex declaration. Little arrows indicate how far we should read at each step and the direction of the arrow indicates the reading direction:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>char const *<span style="color:#f92672">(</span>* const <span style="color:#f92672">(</span>*<span style="color:#f92672">(</span>*ip<span style="color:#f92672">)())[])[]</span>
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span> ip Start at the variable<span style="color:#e6db74">'s name:
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"> '</span>ip<span style="color:#e6db74">' is
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"> ip) Hitting a closing paren: revert
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"> -->
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"> (*ip) Find the matching open paren:
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"> <- '</span>a pointer to<span style="color:#e6db74">'
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"> (*ip)()) The next unmatched closing par:
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"> --> '</span>a <span style="color:#66d9ef">function</span> <span style="color:#f92672">(</span>not expecting
|
|
</span></span><span style="display:flex;"><span> arguments<span style="color:#f92672">)</span><span style="color:#e6db74">'
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"> (*(*ip)()) Find the matching open paren:
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"> <- '</span>returning a pointer to<span style="color:#e6db74">'
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"> (*(*ip)())[]) The next closing par:
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"> --> '</span>an array of<span style="color:#e6db74">'
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"> (* const (*(*ip)())[]) Find the matching open paren:
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"> <-------- '</span>const pointers to<span style="color:#e6db74">'
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"> (* const (*(*ip)())[])[] Read until the end:
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74"> -> '</span>an array of<span style="color:#e6db74">'
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">char const *(* const (*(*ip)())[])[] Read backwards what'</span>s left:
|
|
</span></span><span style="display:flex;"><span><----------- <span style="color:#e6db74">'pointers to const chars'</span>
|
|
</span></span></code></pre></div><p>Collecting all the parts, we get for char <code>const *(* const (*(*ip)())[])[]</code>: <code>ip</code> is a pointer to a function (not expecting arguments), returning a pointer to an array of const pointers to an array of pointers to const chars. This is what <code>ip</code> represents; the recipe can be used to parse any declaration you ever encounter.</p>
|
|
<h3 id="312-namespaces">
|
|
3.1.2: Namespaces
|
|
<a class="anchor" href="#312-namespaces">#</a>
|
|
</h3>
|
|
<p>C++ introduces the notion of a namespace: all symbols are defined in a larger context, called a namespace. Namespaces are used to avoid name conflicts that could arise when a programmer would like to define a function like <code>sin</code> operating on degrees, but does not want to lose the capability of using the standard <code>sin</code> function, operating on radians.</p>
|
|
<p>Namespaces are covered extensively in chapter
|
|
<a href="/cpp/docs/Name-Spaces/">4</a>. For now it should be noted that most compilers require the explicit declaration of a standard namespace: <code>std</code>. So, unless otherwise indicated, it is stressed that all examples in the Annotations now implicitly use the</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">using</span> <span style="color:#66d9ef">namespace</span> std;
|
|
</span></span></code></pre></div><p>declaration. So, if you actually intend to compile examples given in the C++ Annotations, make sure that the sources start with the above using declaration.</p>
|
|
<h3 id="313-the-scope-resolution-operator-">
|
|
3.1.3: The scope resolution operator <strong>::</strong>
|
|
<a class="anchor" href="#313-the-scope-resolution-operator-">#</a>
|
|
</h3>
|
|
<p>C++ introduces several new operators, among which the <strong>scope resolution operator</strong> (<code>::</code>). This operator can be used in situations where a global variable exists having the same name as a local variable:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e"><stdio.h></span><span style="color:#75715e">
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">double</span> counter <span style="color:#f92672">=</span> <span style="color:#ae81ff">50</span>; <span style="color:#75715e">// global variable
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> counter <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>; <span style="color:#75715e">// this refers to the
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> counter <span style="color:#f92672">!=</span> <span style="color:#ae81ff">10</span>; <span style="color:#75715e">// local variable
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#f92672">++</span>counter)
|
|
</span></span><span style="display:flex;"><span> {
|
|
</span></span><span style="display:flex;"><span> printf(<span style="color:#e6db74">"%d</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">"</span>,
|
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672">::</span>counter <span style="color:#75715e">// global variable
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#f92672">/</span> <span style="color:#75715e">// divided by
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> counter); <span style="color:#75715e">// local variable
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> }
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>In the above program the scope operator is used to address a global variable instead of the local variable having the same name. In C++ the scope operator is used extensively, but it is seldom used to reach a global variable shadowed by an identically named local variable. Its main purpose is encountered in chapter
|
|
<a href="/cpp/">7</a>.</p>
|
|
<h3 id="314-cout-cin-and-cerr">
|
|
3.1.4: <strong>cout</strong>, <strong>cin</strong>, and <strong>cerr</strong>
|
|
<a class="anchor" href="#314-cout-cin-and-cerr">#</a>
|
|
</h3>
|
|
<p>Analogous to C, C++ defines standard input and output streams which are available when a program is executed. The streams are:</p>
|
|
<ul>
|
|
<li><code>cout</code>, analogous to <code>stdout</code>,</li>
|
|
<li><code>cin</code>, analogous to <code>stdin</code>,</li>
|
|
<li><code>cerr</code>, analogous to <code>stderr</code>.</li>
|
|
</ul>
|
|
<p>Syntactically these streams are not used as functions: instead, data are written to streams or read from them using the operators <code><<,</code> called the insertion operator and <code>>>,</code> called the extraction operator. This is illustrated in the next example:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e"><iostream></span><span style="color:#75715e">
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">using</span> <span style="color:#66d9ef">namespace</span> std;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> ival;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">char</span> sval[<span style="color:#ae81ff">30</span>];
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"Enter a number:</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">"</span>;
|
|
</span></span><span style="display:flex;"><span> cin <span style="color:#f92672">>></span> ival;
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"And now a string:</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">"</span>;
|
|
</span></span><span style="display:flex;"><span> cin <span style="color:#f92672">>></span> sval;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"The number is: "</span> <span style="color:#f92672"><<</span> ival <span style="color:#f92672"><<</span> <span style="color:#e6db74">"</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">"</span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">"And the string is: "</span> <span style="color:#f92672"><<</span> sval <span style="color:#f92672"><<</span> <span style="color:#e6db74">'\n'</span>;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>This program reads a number and a string from the cin stream (usually the keyboard) and prints these data to cout. With respect to streams, please note:</p>
|
|
<ul>
|
|
<li>The standard streams are declared in the header file <code>iostream</code>. In the examples in the C++ Annotations this header file is often not mentioned explicitly. Nonetheless, it must be included (either directly or indirectly) when these streams are used. Comparable to the use of the <code>using namespace std</code>; clause, the reader is expected to #include <iostream> with all the examples in which the standard streams are used.</li>
|
|
<li>The streams <code>cout</code>, <code>cin</code> and <code>cerr</code> are variables of <strong>so-called class-types</strong>. Such variables are commonly called objects. Classes are discussed in detail in chapter
|
|
<a href="/cpp/">7</a> and are used extensively in C++.</li>
|
|
<li>The stream <code>cin</code> extracts data from a stream and copies the extracted information to variables (e.g., <code>ival</code> in the above example) using the extraction operator (two consecutive <code>></code> characters: <code>>></code>). Later in the Annotations we will describe how operators in C++ can perform quite different actions than what they are defined to do by the language, as is the case here. Function overloading has already been mentioned. In C++ operators can also have multiple definitions, which is called operator overloading.</li>
|
|
<li>The operators which manipulate <code>cin</code>, <code>cout</code> and <code>cerr</code> (i.e., <code>>></code> and <code><<)</code> also manipulate variables of different types. In the above example <code>cout << ival</code> results in the printing of an integer value, whereas <code>cout << "Enter a number"</code> results in the printing of a string. The actions of the operators therefore depend on the types of supplied variables.</li>
|
|
<li>The extraction operator (<code>>></code>) performs a so called type safe assignment to a variable by `extracting’ its value from a text stream. Normally, the extraction operator skips all whitespace characters preceding the values to be extracted.</li>
|
|
<li>Special symbolic constants are used for special situations. Normally a line is terminated by inserting <code>\n</code> or <code>\n</code>. But when inserting the <code>endl</code> symbol the line is terminated followed by the flushing of the stream’s internal buffer. Thus, <code>endl</code> can usually be avoided in favor of <code>\n</code> resulting in somewhat more efficient code.</li>
|
|
</ul>
|
|
<p>The stream objects <code>cin</code>, <code>cout</code> and <code>cerr</code> are not part of the C++ grammar proper. The streams are part of the definitions in the header file <code>iostream</code>. This is comparable to functions like <code>printf</code> that are not part of the C grammar, but were originally written by people who considered such functions important and collected them in a run-time library.</p>
|
|
<p>A program may still use the old-style functions like <code>printf</code> and <code>scanf</code> rather than the new-style streams. The two styles can even be mixed. But streams offer several clear advantages and in many C++ programs have completely replaced the old-style C functions. Some advantages of using streams are:</p>
|
|
<ul>
|
|
<li>Using insertion and extraction operators is type-safe. The format strings which are used with <code>printf</code> and <code>scanf</code> can define wrong format specifiers for their arguments, for which the compiler sometimes can’t warn. In contrast, argument checking with <code>cin</code>, <code>cout</code> and <code>cerr</code> is performed by the compiler. Consequently it isn’t possible to err by providing an int argument in places where, according to the format string, a string argument should appear. With streams there are no format strings.</li>
|
|
<li>The functions <code>printf</code> and <code>scanf</code> (and other functions using format strings) in fact implement a mini-language which is interpreted at run-time. In contrast, with streams the C++ compiler knows exactly which in- or output action to perform given the arguments used. No mini-language here.</li>
|
|
<li>In addition the possibilities of the insertion and extraction operators may be extended allowing objects of classes that didn’t exist when the streams were originally designed to be inserted into or extracted from streams. Mini languages as used with <code>printf</code> cannot be extended.</li>
|
|
<li>The usage of the <strong>left-shift</strong> and <strong>right-shift</strong> operators in the context of the streams illustrates yet another capability of C++: operator overloading allowing us to redefine the actions an operator performs in certain contexts. Coming from C operator overloading requires some getting used to, but after a short little while these overloaded operators feel rather comfortable.</li>
|
|
<li>Streams are independent of the media they operate upon. This (at this point somewhat abstract) notion means that the same code can be used without any modification at all to interface your code to any kind of device. The code using streams can be used when the device is a file on disk; an Internet connection; a digital camera; a DVD device; a satellite link; and much more: you name it. Streams allow your code to be decoupled (independent) of the devices your code is supposed to operate on, which eases maintenance and allows reuse of the same code in new situations.</li>
|
|
</ul>
|
|
<p>The <code>iostream</code> library has a lot more to offer than just <code>cin</code>, <code>cout</code> and <code>cerr</code>. In chapter
|
|
<a href="/cpp/">6</a> <code>iostreams</code> are covered in greater detail. Even though <code>printf</code> and friends can still be used in C++ programs, streams have practically replaced the old-style C I/O functions like <code>printf</code>. If you think you still need to use <code>printf</code> and related functions, think again: in that case you’ve probably not yet completely grasped the possibilities of stream objects.</p>
|
|
<h2 id="32-functions-as-part-of-structs">
|
|
3.2: Functions as part of structs
|
|
<a class="anchor" href="#32-functions-as-part-of-structs">#</a>
|
|
</h2>
|
|
<p>Earlier we noted that functions can be part of structs (see section
|
|
<a href="/cpp/">2.5.13</a>). Such functions are called member functions. This section briefly discusses how to define such functions.</p>
|
|
<p>The code fragment below shows a <code>struct</code> having data fields for a person’s name and address. A function print is included in the <code>struct</code>’s definition:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">Person</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">char</span> name[<span style="color:#ae81ff">80</span>];
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">char</span> address[<span style="color:#ae81ff">80</span>];
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">print</span>();
|
|
</span></span><span style="display:flex;"><span>};
|
|
</span></span></code></pre></div><p>When defining the member function <code>print</code> the structure’s name (<code>Person</code>) and the scope resolution operator (<code>::</code>) are used:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> Person<span style="color:#f92672">::</span>print()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"Name: "</span> <span style="color:#f92672"><<</span> name <span style="color:#f92672"><<</span> <span style="color:#e6db74">"</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">"</span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">"Address: "</span> <span style="color:#f92672"><<</span> address <span style="color:#f92672"><<</span> <span style="color:#e6db74">'\n'</span>;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>The implementation of <code>Person::print</code> shows how the fields of the struct can be accessed without using the structure’s type name. Here the function <code>Person::print</code> prints a variable name. Since <code>Person::print</code> is itself a part of struct <code>person</code>, the variable name implicitly refers to the same type.</p>
|
|
<p>This struct <code>Person</code> could be used as follows:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>Person person;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span>strcpy(person.name, <span style="color:#e6db74">"Karel"</span>);
|
|
</span></span><span style="display:flex;"><span>strcpy(person.address, <span style="color:#e6db74">"Marskramerstraat 33"</span>);
|
|
</span></span><span style="display:flex;"><span>person.print();
|
|
</span></span></code></pre></div><p>The advantage of member functions is that the called function automatically accesses the data fields of the structure for which it was invoked. In the statement <code>person.print()</code> the object <code>person</code> is the substrate: the variables <code>name</code> and <code>address</code> that are used in the code of print refer to the data stored in the <code>person</code> object.</p>
|
|
<h3 id="321-data-hiding-public-private-and-class">
|
|
3.2.1: Data hiding: <strong>public</strong>, <strong>private</strong> and <strong>class</strong>
|
|
<a class="anchor" href="#321-data-hiding-public-private-and-class">#</a>
|
|
</h3>
|
|
<p>As mentioned before (see section
|
|
<a href="/cpp/">2.3</a>), C++ contains specialized syntactic possibilities to implement data hiding. Data hiding is the capability of sections of a program to hide its data from other sections. This results in very clean data definitions. It also allows these sections to enforce the integrity of their data.</p>
|
|
<p>C++ has three keywords that are related to data hiding: <code>private</code>, <code>protected</code> and <code>public</code>. These keywords can be used in the definition of structs. The keyword <code>public</code> allows all subsequent fields of a structure to be accessed by all code; the keyword <code>private</code> only allows code that is part of the struct itself to access subsequent fields. The keyword <code>protected</code> is discussed in chapter
|
|
<a href="/cpp/">13</a>, and is somewhat outside of the scope of the current discussion.</p>
|
|
<p><strong>In a struct all fields are public, unless explicitly stated otherwise</strong>. Using this knowledge we can expand the struct <code>Person</code>:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">Person</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">private</span><span style="color:#f92672">:</span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">char</span> d_name[<span style="color:#ae81ff">80</span>];
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">char</span> d_address[<span style="color:#ae81ff">80</span>];
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span><span style="color:#f92672">:</span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">void</span> setName(<span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span>n);
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">setAddress</span>(<span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span>a);
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">print</span>();
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">name</span>();
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">address</span>();
|
|
</span></span><span style="display:flex;"><span>};
|
|
</span></span></code></pre></div><p>As the data fields <code>d_name</code> and <code>d_address</code> are in a private section they are only accessible to the member functions which are defined in the struct: these are the functions <code>setName</code>, <code>setAddress</code> etc.. As an illustration consider the following code:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>Person fbb;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span>fbb.setName(<span style="color:#e6db74">"Frank"</span>); <span style="color:#75715e">// OK, setName is public
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>strcpy(fbb.d_name, <span style="color:#e6db74">"Knarf"</span>); <span style="color:#75715e">// error, x.d_name is private
|
|
</span></span></span></code></pre></div><p>Data integrity is implemented as follows: the actual data of a struct <code>Person</code> are mentioned in the structure definition. The data are accessed by the outside world using special functions that are also part of the definition. These member functions control all traffic between the data fields and other parts of the program and are therefore also called <strong>interface functions</strong>. The thus implemented data hiding is illustrated in Figure 2.</p>
|
|
<p>
|
|
<img src="https://static.cyub.vip/images/c++_annotations/first/datahiding.gif" alt="Figure 2: Private data and public interface functions of the class Person.
|
|
" /></p>
|
|
<p>The members <code>setName</code> and <code>setAddress</code> are declared with <code>char const *</code> parameters. This indicates that the functions will not alter the strings which are supplied as their arguments. Analogously, the members <code>name</code> and <code>address</code> return <code>char const *</code>: the compiler prevents callers of those members from modifying the information made accessible through the return values of those members.</p>
|
|
<p>Two examples of member functions of the struct <code>Person</code> are shown below:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> Person<span style="color:#f92672">::</span>setName(<span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span>n)
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> strncpy(d_name, n, <span style="color:#ae81ff">79</span>);
|
|
</span></span><span style="display:flex;"><span> d_name[<span style="color:#ae81ff">79</span>] <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span>Person<span style="color:#f92672">::</span>name()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> d_name;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>The power of member functions and of the concept of data hiding results from the abilities of member functions to perform special tasks, e.g., checking the validity of the data. In the above example <code>setName</code> copies only up to 79 characters from its argument to the data member <code>name</code>, thereby avoiding a buffer overflow.</p>
|
|
<p>Another illustration of the concept of data hiding is the following. As an alternative to member functions that keep their data in memory a library could be developed featuring member functions storing data on file. To convert a program storing <code>Person</code> structures in memory to one that stores the data on disk no special modifications are required. After recompilation and linking the program to a new library it is converted from storage in memory to storage on disk. This example illustrates a broader concept than data hiding; it illustrates encapsulation. Data hiding is a kind of encapsulation. Encapsulation in general results in reduced coupling of different sections of a program. This in turn greatly enhances reusability and maintainability of the resulting software. By having the structure encapsulate the actual storage medium the program using the structure becomes independent of the actual storage medium that is used.</p>
|
|
<p>Though data hiding can be implemented using structs, more often (almost always) classes are used instead. <strong>A class is a kind of struct, except that a class uses private access by default, whereas structs use public access by default</strong>. The definition of a <strong>class Person</strong> is therefore identical to the one shown above, except that the keyword class has replaced struct while the initial private: clause can be omitted. Our typographic suggestion for class names (and other type names defined by the programmer) is to start with a capital character to be followed by the remainder of the type name using lower case letters (e.g., <code>Person</code>).</p>
|
|
<h3 id="322-structs-in-c-vs-structs-in-c">
|
|
3.2.2: Structs in C vs. structs in C++
|
|
<a class="anchor" href="#322-structs-in-c-vs-structs-in-c">#</a>
|
|
</h3>
|
|
<p>In this section we’ll discuss an important difference between C and C++ structs and (member) functions. In C it is common to define several functions to process a struct, which then require a pointer to the struct as one of their arguments. An imaginary C header file showing this concept is:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">/* definition of a struct PERSON This is C */</span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">struct</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">char</span> name[<span style="color:#ae81ff">80</span>];
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">char</span> address[<span style="color:#ae81ff">80</span>];
|
|
</span></span><span style="display:flex;"><span>} PERSON;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#75715e">/* some functions to manipulate PERSON structs */</span>
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#75715e">/* initialize fields with a name and address */</span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">initialize</span>(PERSON <span style="color:#f92672">*</span>p, <span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span>nm,
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span>adr);
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#75715e">/* print information */</span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">print</span>(PERSON <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span>p);
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#75715e">/* etc.. */</span>
|
|
</span></span></code></pre></div><p>In C++, the declarations of the involved functions are put inside the definition of the struct or class. The argument denoting which struct is involved is no longer needed.</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Person</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">char</span> d_name[<span style="color:#ae81ff">80</span>];
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">char</span> d_address[<span style="color:#ae81ff">80</span>];
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">public</span><span style="color:#f92672">:</span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">void</span> initialize(<span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span>nm, <span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span>adr);
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">print</span>();
|
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// etc..
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>};
|
|
</span></span></code></pre></div><p>In C++ the struct parameter is not used. A C function call such as:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>PERSON x;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span>initialize(<span style="color:#f92672">&</span>x, <span style="color:#e6db74">"some name"</span>, <span style="color:#e6db74">"some address"</span>);
|
|
</span></span></code></pre></div><p>becomes in C++:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>Person x;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span>x.initialize(<span style="color:#e6db74">"some name"</span>, <span style="color:#e6db74">"some address"</span>);
|
|
</span></span></code></pre></div><h2 id="33-several-additions-to-cs-grammar">
|
|
3.3: Several additions to C’s grammar
|
|
<a class="anchor" href="#33-several-additions-to-cs-grammar">#</a>
|
|
</h2>
|
|
<h3 id="331-references">
|
|
3.3.1: References
|
|
<a class="anchor" href="#331-references">#</a>
|
|
</h3>
|
|
<p>In addition to the common ways to define variables (plain variables or pointers) C++ introduces references defining synonyms for variables. A reference to a variable is like an alias; the variable and the reference can both be used in statements involving the variable:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> int_value;
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#f92672">&</span>ref <span style="color:#f92672">=</span> int_value;
|
|
</span></span></code></pre></div><p>In the above example a variable <code>int_value</code> is defined. Subsequently a reference <code>ref</code> is defined, which (due to its initialization) refers to the same memory location as <code>int_value</code>. In the definition of <code>ref</code>, the reference operator <code>&</code> indicates that <code>ref</code> is not itself an int but a reference to one. The two statements</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#f92672">++</span>int_value;
|
|
</span></span><span style="display:flex;"><span><span style="color:#f92672">++</span>ref;
|
|
</span></span></code></pre></div><p>have the same effect: they increment <code>int_value</code>’s value. Whether that location is called <code>int_value</code> or ref does not matter.</p>
|
|
<p>References serve an important function in C++ as a means to pass modifiable arguments to functions. E.g., in standard C, a function that increases the value of its argument by five and returning nothing needs a pointer parameter:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">increase</span>(<span style="color:#66d9ef">int</span> <span style="color:#f92672">*</span>valp) <span style="color:#75715e">// expects a pointer
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>{ <span style="color:#75715e">// to an int
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#f92672">*</span>valp <span style="color:#f92672">+=</span> <span style="color:#ae81ff">5</span>;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> x;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span> increase(<span style="color:#f92672">&</span>x); <span style="color:#75715e">// pass x's address
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
|
|
</span></span></code></pre></div><p>This construction can also be used in C++ but the same effect is also achieved using a reference:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">increase</span>(<span style="color:#66d9ef">int</span> <span style="color:#f92672">&</span>valr) <span style="color:#75715e">// expects a reference
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>{ <span style="color:#75715e">// to an int
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> valr <span style="color:#f92672">+=</span> <span style="color:#ae81ff">5</span>;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> x;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span> increase(x); <span style="color:#75715e">// passed as reference
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
|
|
</span></span></code></pre></div><p>It is arguable whether code such as the above should be preferred over C’s method, though. The statement <code>increase (x)</code> suggests that not x itself but a copy is passed. Yet the value of x changes because of the way <code>increase()</code> is defined. However, references can also be used to pass objects that are only inspected (without the need for a copy or a <code>const *</code>) or to pass objects whose modification is an accepted side-effect of their use. In those cases using references are strongly preferred over existing alternatives like copy by value or passing pointers.</p>
|
|
<p>Behind the scenes references are implemented using pointers. So, as far as the compiler is concerned references in C++ are just const pointers. With references, however, the programmer does not need to know or to bother about levels of indirection. An important distinction between plain pointers and references is of course that with references no indirection takes place. For example:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">extern</span> <span style="color:#66d9ef">int</span> <span style="color:#f92672">*</span>ip;
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">extern</span> <span style="color:#66d9ef">int</span> <span style="color:#f92672">&</span>ir;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span>ip <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#75715e">// reassigns ip, now a 0-pointer
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>ir <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#75715e">// ir unchanged, the int variable it refers to
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#75715e">// is now 0.
|
|
</span></span></span></code></pre></div><p>In order to prevent confusion, we suggest to adhere to the following:</p>
|
|
<ul>
|
|
<li>In those situations where a function does not alter its parameters of a built-in or pointer type, value parameters can be used:</li>
|
|
</ul>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">some_func</span>(<span style="color:#66d9ef">int</span> val)
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> val <span style="color:#f92672"><<</span> <span style="color:#e6db74">'\n'</span>;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> x;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span> some_func(x); <span style="color:#75715e">// a copy is passed
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
|
|
</span></span></code></pre></div><ul>
|
|
<li>When a function explicitly must change the values of its arguments, a pointer parameter is preferred. These pointer parameters should preferably be the function’s initial parameters. This is called return by argument.</li>
|
|
</ul>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">by_pointer</span>(<span style="color:#66d9ef">int</span> <span style="color:#f92672">*</span>valp)
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672">*</span>valp <span style="color:#f92672">+=</span> <span style="color:#ae81ff">5</span>;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><ul>
|
|
<li>When a function doesn’t change the value of its class- or struct-type arguments, or if the modification of the argument is a trivial side-effect (e.g., the argument is a stream) references can be used. <strong>Const-references</strong> should be used if the function does not modify the argument:</li>
|
|
</ul>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">by_reference</span>(string <span style="color:#66d9ef">const</span> <span style="color:#f92672">&</span>str)
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> str; <span style="color:#75715e">// no modification of str
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span> ()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> x <span style="color:#f92672">=</span> <span style="color:#ae81ff">7</span>;
|
|
</span></span><span style="display:flex;"><span> by_pointer(<span style="color:#f92672">&</span>x); <span style="color:#75715e">// a pointer is passed
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#75715e">// x might be changed
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> string str(<span style="color:#e6db74">"hello"</span>);
|
|
</span></span><span style="display:flex;"><span> by_reference(str); <span style="color:#75715e">// str is not altered
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
|
|
</span></span></code></pre></div><ul>
|
|
<li>References play an important role in cases where the argument is not changed by the function but where it is undesirable to copy the argument to initialize the parameter. Such a situation occurs when a large object is passed as argument, or is returned by the function. In these cases the copying operation tends to become a significant factor, as the entire object must be copied. In these cases references are preferred.</li>
|
|
</ul>
|
|
<p>If the argument isn’t modified by the function, or if the caller shouldn’t modify the returned information, the <code>const</code> keyword should be used. Consider the following example:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">Person</span> <span style="color:#75715e">// some large structure
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">char</span> name[<span style="color:#ae81ff">80</span>];
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">char</span> address[<span style="color:#ae81ff">90</span>];
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">double</span> salary;
|
|
</span></span><span style="display:flex;"><span>};
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span>Person person[<span style="color:#ae81ff">50</span>]; <span style="color:#75715e">// database of persons
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// printperson expects a
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#75715e">// reference to a structure
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#75715e">// but won't change it
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">printperson</span> (Person <span style="color:#66d9ef">const</span> <span style="color:#f92672">&</span>subject)
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"Name: "</span> <span style="color:#f92672"><<</span> subject.name <span style="color:#f92672"><<</span> <span style="color:#e6db74">'\n'</span> <span style="color:#f92672"><<</span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">"Address: "</span> <span style="color:#f92672"><<</span> subject.address <span style="color:#f92672"><<</span> <span style="color:#e6db74">'\n'</span>;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// get a person by index value
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>Person <span style="color:#66d9ef">const</span> <span style="color:#f92672">&</span>personIdx(<span style="color:#66d9ef">int</span> index)
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> person[index]; <span style="color:#75715e">// a reference is returned,
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>} <span style="color:#75715e">// not a copy of person[index]
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> Person boss;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span> printperson(boss); <span style="color:#75715e">// no pointer is passed,
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#75715e">// so `boss' won't be
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#75715e">// altered by the function
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> printperson(personIdx(<span style="color:#ae81ff">5</span>));
|
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// references, not copies
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#75715e">// are passed here
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
|
|
</span></span></code></pre></div><p>Furthermore, note that there is yet another reason for using references when passing objects as function arguments. When passing a reference to an object, the activation of a so called copy constructor is avoided. Copy constructors are covered in chapter
|
|
<a href="/cpp/">9</a>.</p>
|
|
<p>References could result in extremely ugly code. A function may return a reference to a variable, as in the following example:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#f92672">&</span>func()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">int</span> value;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> value;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>This allows the use of the following constructions:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>func() <span style="color:#f92672">=</span> <span style="color:#ae81ff">20</span>;
|
|
</span></span><span style="display:flex;"><span>func() <span style="color:#f92672">+=</span> func();
|
|
</span></span></code></pre></div><p>It is probably superfluous to note that such constructions should normally not be used. Nonetheless, there are situations where it is useful to return a reference. We have actually already seen an example of this phenomenon in our previous discussion of streams. In a statement like <code>cout << "Hello" << '\n'</code>; the insertion operator returns a reference to <code>cout</code>. So, in this statement first the <code>Hello</code> is inserted into <code>cout</code>, producing a reference to <code>cout</code>. Through this reference the <code>\n</code> is then inserted in the <code>cout</code> object, again producing a reference to <code>cout</code>, which is then ignored.</p>
|
|
<p>Several differences between pointers and references are pointed out in the next list below:</p>
|
|
<ul>
|
|
<li>A reference cannot exist by itself, i.e., without something to refer to. A declaration of a reference like <code>int &ref</code>; is not allowed; what would <code>ref</code> refer to?</li>
|
|
<li>References can be declared as external. These references were initialized elsewhere.</li>
|
|
<li>References may exist as parameters of functions: they are initialized when the function is called.</li>
|
|
<li>References may be used in the return types of functions. In those cases the function determines what the return value refers to.</li>
|
|
<li>References may be used as data members of classes. We return to this usage later.</li>
|
|
<li>Pointers are variables by themselves. They point at something concrete or just ``at nothing’'.</li>
|
|
<li>References are aliases for other variables and cannot be re-aliased to another variable. Once a reference is defined, it refers to its particular variable.</li>
|
|
<li>Pointers (except for const pointers) can be reassigned to point to different variables.</li>
|
|
<li>When an <strong>address-of operator &</strong> is used with a reference, the expression yields the address of the variable to which the reference applies. In contrast, ordinary pointers are variables themselves, so the address of a pointer variable has nothing to do with the address of the variable pointed to.</li>
|
|
</ul>
|
|
<h3 id="332-rvalue-references">
|
|
3.3.2: Rvalue References
|
|
<a class="anchor" href="#332-rvalue-references">#</a>
|
|
</h3>
|
|
<p>In C++, temporary (<code>rvalue</code>) values are indistinguishable from <code>const &</code> types. C++ introduces a new reference type called an rvalue reference, which is defined as <code>typename &&</code>.</p>
|
|
<p>The name rvalue reference is derived from assignment statements, where the variable to the left of the assignment operator is called an lvalue and the expression to the right of the assignment operator is called an rvalue. Rvalues are often temporary, anonymous values, like values returned by functions.</p>
|
|
<p>In this parlance the C++ reference should be considered an lvalue reference (using the notation <code>typename &</code>). They can be contrasted to rvalue references (using the notation <code>typename &&</code>).</p>
|
|
<p>The key to understanding rvalue references is the concept of an anonymous variable. An anonymous variable has no name and this is the distinguishing feature for the compiler to associate it automatically with an rvalue reference if it has a choice. Before introducing some interesting constructions let’s first have a look at some standard situations where lvalue references are used. The following function returns a temporary (anonymous) value:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">intVal</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">5</span>;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>Although <code>intVal</code>’s return value can be assigned to an int variable it requires copying, which might become prohibitive when a function does not return an int but instead some large object. A reference or pointer cannot be used either to collect the anonymous return value as the return value won’t survive beyond that. So the following is illegal (as noted by the compiler):</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#f92672">&</span>ir <span style="color:#f92672">=</span> intVal(); <span style="color:#75715e">// fails: refers to a temporary
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">int</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">&</span>ic <span style="color:#f92672">=</span> intVal(); <span style="color:#75715e">// OK: immutable temporary
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">int</span> <span style="color:#f92672">*</span>ip <span style="color:#f92672">=</span> <span style="color:#f92672">&</span>intVal(); <span style="color:#75715e">// fails: no lvalue available
|
|
</span></span></span></code></pre></div><p>Apparently it is not possible to modify the temporary returned by <code>intVal</code>. But now consider these functions:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">receive</span>(<span style="color:#66d9ef">int</span> <span style="color:#f92672">&</span>value) <span style="color:#75715e">// note: lvalue reference
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>{
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"int value parameter</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">"</span>;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">receive</span>(<span style="color:#66d9ef">int</span> <span style="color:#f92672">&&</span>value) <span style="color:#75715e">// note: rvalue reference
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>{
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"int R-value parameter</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">"</span>;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>and let’s call this function from main:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> receive(<span style="color:#ae81ff">18</span>);
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> value <span style="color:#f92672">=</span> <span style="color:#ae81ff">5</span>;
|
|
</span></span><span style="display:flex;"><span> receive(value);
|
|
</span></span><span style="display:flex;"><span> receive(intVal());
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>This program produces the following output:</p>
|
|
<pre tabindex="0"><code>int R-value parameter
|
|
int value parameter
|
|
int R-value parameter
|
|
</code></pre><p>The program’s output shows the compiler selecting <code>receive(int &&value)</code> in all cases where it receives an anonymous int as its argument. Note that this includes <code>receive(18)</code>: a value 18 has no name and thus <code>receive(int &&value)</code> is called. Internally, it actually uses a temporary variable to store the 18, as is shown by the following example which modifies <code>receive</code>:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">receive</span>(<span style="color:#66d9ef">int</span> <span style="color:#f92672">&&</span>value)
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672">++</span>value;
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"int R-value parameter, now: "</span> <span style="color:#f92672"><<</span> value <span style="color:#f92672"><<</span> <span style="color:#e6db74">'\n'</span>;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// displays 19 and 6, respectively.
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
|
|
</span></span></code></pre></div><p>Contrasting <code>receive(int &value)</code> with <code>receive(int &&value)</code> has nothing to do with <code>int &value</code> not being a const reference. If <code>receive(int const &value)</code> is used the same results are obtained. Bottom line: the compiler selects the overloaded function using the rvalue reference if the function is passed an anonymous value.</p>
|
|
<p>The compiler runs into problems if <code>void receive(int &value)</code> is replaced by <code>void receive(int value)</code>, though. When confronted with the choice between a value parameter and a reference parameter (either lvalue or rvalue) it cannot make a decision and reports an ambiguity. In practical contexts this is not a problem. Rvalue references were added to the language in order to be able to distinguish the two forms of references: named values (for which lvalue references are used) and anonymous values (for which rvalue references are used).</p>
|
|
<p>It is this distinction that allows the implementation of move semantics and perfect forwarding. At this point the concept of move semantics cannot yet fully be discussed (but see section
|
|
<a href="/cpp/">9.7</a> for a more thorough discussion) but it is very well possible to illustrate the underlying ideas.</p>
|
|
<p>Consider the situation where a function returns a struct <code>Data</code> containing a pointer to a dynamically allocated <code>NTBS</code>. We agree that <code>Data</code> objects are only used after initialization, for which two <code>init</code> functions are available. As an aside: when <code>Data</code> objects are no longer required the memory pointed at by <code>text</code> must again be returned to the operating system; assume that that task is properly performed.</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">Data</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span>text;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">init</span>(<span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span>txt); <span style="color:#75715e">// initialize text from txt
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">init</span>(Data <span style="color:#66d9ef">const</span> <span style="color:#f92672">&</span>other)
|
|
</span></span><span style="display:flex;"><span> {
|
|
</span></span><span style="display:flex;"><span> text <span style="color:#f92672">=</span> strdup(other.text);
|
|
</span></span><span style="display:flex;"><span> }
|
|
</span></span><span style="display:flex;"><span>};
|
|
</span></span></code></pre></div><p>There’s also this interesting function:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>Data <span style="color:#a6e22e">dataFactory</span>(<span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span>text);
|
|
</span></span></code></pre></div><p>Its implementation is irrelevant, but it returns a (temporary) <code>Data</code> object initialized with <code>text</code>. Such temporary objects cease to exist once the statement in which they are created end.</p>
|
|
<p>Now we’ll use <code>Data</code>:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> Data d1;
|
|
</span></span><span style="display:flex;"><span> d1.init(dataFactory(<span style="color:#e6db74">"object"</span>));
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>Here the <code>init</code> function duplicates the <code>NTBS</code> stored in the temporary object. Immediately thereafter the temporary object ceases to exist. If you think about it, then you realize that that’s a bit over the top:</p>
|
|
<ul>
|
|
<li>the <code>dataFactory</code> function uses <code>init</code> to initialize the <code>text</code> variable of its temporary Data object. For that it uses <code>strdup</code>;</li>
|
|
<li>the <code>d1.init</code> function then also uses <code>strdup</code> to initialize <code>d1.text</code>;</li>
|
|
<li>the statement ends, and the temporary object ceases to exist.</li>
|
|
</ul>
|
|
<p>That’s two <code>strdup</code> calls, but the temporary <code>Data</code> object thereafter is never used again.</p>
|
|
<p>To handle cases like these rvalue reference were introduced. We add the following function to the struct <code>Data</code>:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">init</span>(Data <span style="color:#f92672">&&</span>tmp)
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> text <span style="color:#f92672">=</span> tmp.text; <span style="color:#75715e">// (1)
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> tmp.text <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#75715e">// (2)
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
|
|
</span></span></code></pre></div><p>Now, when the compiler translates <code>d1.init(dataFactory("object"))</code> it notices that <code>dataFactory</code> returns a (temporary) object, and because of that it uses the <code>init(Data &&tmp)</code> function. As we know that the <code>tmp</code> object ceases to exist after executing the statement in which it is used, the <code>d1</code> object (at (1)) grabs the temporary object’s <code>text</code> value, and then (at (2)) assigns 0 to <code>other.text</code> so that the temporary object’s <code>free(text)</code> action does no harm.</p>
|
|
<p>Thus, struct <code>Data</code> suddenly has become move-aware and implements move semantics, removing the (extra copy) drawback of the previous approach, and instead of making an extra copy of the temporary object’s NTBS the pointer value is simply transferred to its new owner.</p>
|
|
<h3 id="333-lvalues-rvalues-and-more">
|
|
3.3.3: Lvalues, rvalues and more
|
|
<a class="anchor" href="#333-lvalues-rvalues-and-more">#</a>
|
|
</h3>
|
|
<p>Although this section contains forward references to chapters
|
|
<a href="/cpp/">5</a>,
|
|
<a href="/cpp/">7</a>, and
|
|
<a href="/cpp/">16</a>, its topic best fits the current chapter. This section can be skipped without loss of continuity, and you might consider returning to it once you’re familiar with the content of these future chapters.</p>
|
|
<p>Historically, the C programming language distinguished between lvalues and rvalues. The terminology was based on assignment expressions, where the expression to the left of the assignment operator receives a value (e.g., it referred to a location in memory where a value could be written into, like a variable), while the expression to the right of the assignment operator only had to represent a value (it could be a temporary variable, a constant value or the value stored in a variable):</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>lvalue <span style="color:#f92672">=</span> rvalue;
|
|
</span></span></code></pre></div><p>C++ adds to this basic distinction several new ways of referring to expressions:</p>
|
|
<ul>
|
|
<li><strong>lvalue</strong>: an lvalue in C++ has the same meaning as in C. It refers to a location where a value can be stored, like a variable, a reference to a variable, or a dereferenced pointer.</li>
|
|
<li><strong>xvalue</strong>: an xvalue indicates an expiring value. An expiring value refers to an object (cf. chapter
|
|
<a href="/cpp/">7</a>) just before its lifetime ends. Such objects normally have to make sure that resources they own (like dynamically allocated memory) also cease to exist, but such resources may, just before the object’s lifetime ends, be moved to another location, thus preventing their destruction.</li>
|
|
<li><strong>glvalue</strong>: a glvalue is a generalized lvalue. A generalized lvalue refers to anything that may receive a value. It is either an lvalue or an xvalue.</li>
|
|
<li><strong>prvalue</strong>: a prvalue is a pure rvalue: a literal value (like 1.2e3) or an immutable object (e.g., the value returned from a function returning a constant <code>std::string</code> (cf. chapter
|
|
<a href="/cpp/">5</a>)).</li>
|
|
</ul>
|
|
<p>An expression’s value is an xvalue if it is:</p>
|
|
<ul>
|
|
<li>
|
|
<p>the value returned by a function returning an rvalue reference to an object;</p>
|
|
</li>
|
|
<li>
|
|
<p>an object that is cast to an rvalue reference;</p>
|
|
</li>
|
|
<li>
|
|
<p>an expression accessing a non-static class data member whose object is</p>
|
|
<ul>
|
|
<li>an <strong>xvalue</strong>, or</li>
|
|
<li>a <em><em>.</em> (pointer-to-member) expression</em>* (cf. chapter
|
|
<a href="/cpp/">16</a>) in which the left-hand side operand is an xvalue and the right-hand side operand is a pointer to a data member.</li>
|
|
</ul>
|
|
<p>The effect of this rule is that named rvalue references are treated as lvalues and anonymous rvalue references to objects are treated as xvalues.</p>
|
|
<p>Rvalue references to functions are treated as lvalues whether anonymous or not.</p>
|
|
</li>
|
|
</ul>
|
|
<p>Here is a small example. Consider this simple struct:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">Demo</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> d_value;
|
|
</span></span><span style="display:flex;"><span>};
|
|
</span></span></code></pre></div><p>In addition we have these function declarations and definitions:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>Demo <span style="color:#f92672">&&</span><span style="color:#66d9ef">operator</span><span style="color:#f92672">+</span>(Demo <span style="color:#66d9ef">const</span> <span style="color:#f92672">&</span>lhs, Demo <span style="color:#66d9ef">const</span> <span style="color:#f92672">&</span>rhs);
|
|
</span></span><span style="display:flex;"><span>Demo <span style="color:#f92672">&&</span>factory();
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span>Demo demo;
|
|
</span></span><span style="display:flex;"><span>Demo <span style="color:#f92672">&&</span>rref <span style="color:#f92672">=</span> <span style="color:#66d9ef">static_cast</span><span style="color:#f92672"><</span>Demo <span style="color:#f92672">&&></span>(demo);
|
|
</span></span></code></pre></div><p>Expressions like</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>factory();
|
|
</span></span><span style="display:flex;"><span>factory().d_value;
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">static_cast</span><span style="color:#f92672"><</span>Demo <span style="color:#f92672">&&></span>(demo);
|
|
</span></span><span style="display:flex;"><span>demo <span style="color:#f92672">+</span> demo
|
|
</span></span></code></pre></div><p>are xvalues. However, the expression</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>rref;
|
|
</span></span></code></pre></div><p>is an lvalue.</p>
|
|
<p>In many situations it’s not particularly important to know what kind of lvalue or what kind of rvalue is actually used. In the C++ Annotations the term <strong>lhs</strong> (left hand side) is frequently used to indicate an operand that’s written to the left of a binary operator, while the term <strong>rhs</strong> (right hand side) is frequently used to indicate an operand that’s written to the right of a binary operator. <code>Lhs</code> and <code>rhs</code> operands could actually be <code>gvalues</code> (e.g., when representing ordinary variables), but they could also be prvalues (e.g., numeric values added together using the addition operator). Whether or not <code>lhs</code> and <code>rhs</code> operands are <code>gvalues</code> or <code>lvalues</code> can always be determined from the context in which they are used.</p>
|
|
<h3 id="334-strongly-typed-enumerations">
|
|
3.3.4: Strongly typed enumerations
|
|
<a class="anchor" href="#334-strongly-typed-enumerations">#</a>
|
|
</h3>
|
|
<p>Enumeration values in C++ are in fact int values, thereby bypassing type safety. E.g., values of different enumeration types may be compared for (in)equality, albeit through a (static) type cast.</p>
|
|
<p>Another problem with the current enum type is that their values are not restricted to the enum type name itself, but to the scope where the enumeration is defined. As a consequence, two enumerations having the same scope cannot have identical names.</p>
|
|
<p>Such problems are solved by defining enum classes. An enum class can be defined as in the following example:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">enum</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">SafeEnum</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> NOT_OK, <span style="color:#75715e">// 0, by implication
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> OK <span style="color:#f92672">=</span> <span style="color:#ae81ff">10</span>,
|
|
</span></span><span style="display:flex;"><span> MAYBE_OK <span style="color:#75715e">// 11, by implication
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>};
|
|
</span></span></code></pre></div><p>Enum classes use int values by default, but the used value type can easily be changed using the : type notation, as in:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">enum</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">CharEnum</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">char</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> NOT_OK,
|
|
</span></span><span style="display:flex;"><span> OK
|
|
</span></span><span style="display:flex;"><span>};
|
|
</span></span></code></pre></div><p>To use a value defined in an enum class its enumeration name must be provided as well. E.g., <code>OK</code> is not defined, <code>CharEnum::OK</code> is.</p>
|
|
<p>Using the data type specification (noting that it defaults to int) it is possible to use enum class forward declarations. E.g.,</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">enum</span> <span style="color:#a6e22e">Enum1</span>; <span style="color:#75715e">// Illegal: no size available
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">enum</span> <span style="color:#a6e22e">Enum2</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">int</span>; <span style="color:#75715e">// Legal: explicitly declared type
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">enum</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Enum3</span>; <span style="color:#75715e">// Legal: default int type is used
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">enum</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Enum4</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">char</span>; <span style="color:#75715e">// Legal: explicitly declared type
|
|
</span></span></span></code></pre></div><p>A sequence of symbols of a strongly typed enumeration can also be indicated in a switch using the ellipsis syntax, as shown in the next example:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>SafeEnum <span style="color:#a6e22e">enumValue</span>();
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">switch</span> (enumValue())
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">case</span> SafeEnum<span style="color:#f92672">::</span>NOT_OK ... SafeEnum<span style="color:#f92672">::</span>OK:
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"Status is known</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">"</span>;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">break</span>;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">default</span><span style="color:#f92672">:</span>
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"Status unknown</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">"</span>;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">break</span>;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><h3 id="335-initializer-lists">
|
|
3.3.5: Initializer lists
|
|
<a class="anchor" href="#335-initializer-lists">#</a>
|
|
</h3>
|
|
<p>The C language defines the initializer list as a list of values enclosed by curly braces, possibly themselves containing initializer lists. In C these initializer lists are commonly used to initialize arrays and structs.</p>
|
|
<p>C++ extends this concept by introducing the type <code>initializer_list<Type></code> where Type is replaced by the type name of the values used in the initializer list. Initializer lists in C++ are, like their counterparts in C, recursive, so they can also be used with multi-dimensional arrays, structs and classes.</p>
|
|
<p>Before using the <code>initializer_list</code> the <code><initializer_list></code> header file must be included.</p>
|
|
<p>Like in C, initializer lists consist of a list of values surrounded by curly braces. But unlike C, functions can define initializer list parameters. E.g.,</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">values</span>(std<span style="color:#f92672">::</span>initializer_list<span style="color:#f92672"><</span><span style="color:#66d9ef">int</span><span style="color:#f92672">></span> iniValues)
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>A function like values could be called as follows:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>values({<span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">3</span>, <span style="color:#ae81ff">5</span>, <span style="color:#ae81ff">7</span>, <span style="color:#ae81ff">11</span>, <span style="color:#ae81ff">13</span>});
|
|
</span></span></code></pre></div><p>The initializer list appears as an argument which is a list of values surrounded by curly braces. Due to the recursive nature of initializer lists a two-dimensional series of values can also be passes, as shown in the next example:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">values2</span>(std<span style="color:#f92672">::</span>initializer_list<span style="color:#f92672"><</span>std<span style="color:#f92672">::</span>initializer_list<span style="color:#f92672"><</span><span style="color:#66d9ef">int</span><span style="color:#f92672">>></span> iniValues)
|
|
</span></span><span style="display:flex;"><span>{}
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span>values2({{<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>}, {<span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">3</span>}, {<span style="color:#ae81ff">3</span>, <span style="color:#ae81ff">5</span>}, {<span style="color:#ae81ff">4</span>, <span style="color:#ae81ff">7</span>}, {<span style="color:#ae81ff">5</span>, <span style="color:#ae81ff">11</span>}, {<span style="color:#ae81ff">6</span>, <span style="color:#ae81ff">13</span>}});
|
|
</span></span></code></pre></div><p>Initializer lists are constant expressions and cannot be modified. However, their size and values may be retrieved using their <code>size</code>, <code>begin</code>, and <code>end</code> members as follows:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">values</span>(initializer_list<span style="color:#f92672"><</span><span style="color:#66d9ef">int</span><span style="color:#f92672">></span> iniValues)
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"Initializer list having "</span> <span style="color:#f92672"><<</span> iniValues.size() <span style="color:#f92672"><<</span> <span style="color:#e6db74">"values</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">"</span>;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">for</span>
|
|
</span></span><span style="display:flex;"><span> (
|
|
</span></span><span style="display:flex;"><span> initializer_list<span style="color:#f92672"><</span><span style="color:#66d9ef">int</span><span style="color:#f92672">>::</span>const_iterator begin <span style="color:#f92672">=</span> iniValues.begin();
|
|
</span></span><span style="display:flex;"><span> begin <span style="color:#f92672">!=</span> iniValues.end();
|
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672">++</span>begin
|
|
</span></span><span style="display:flex;"><span> )
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"Value: "</span> <span style="color:#f92672"><<</span> <span style="color:#f92672">*</span>begin <span style="color:#f92672"><<</span> <span style="color:#e6db74">'\n'</span>;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>Initializer lists can also be used to initialize objects of classes (cf. section
|
|
<a href="/cpp/">7.5</a>, which also summarizes the facilities of initializer lists).</p>
|
|
<p>Implicit conversions, also called narrowing conversions are not allowed when specifying values of initializer lists. Narrowing conversions are encountered when values are used of a type whose range is larger than the type specified when defining the initializer list. For example</p>
|
|
<ul>
|
|
<li>specifying float or double values to define initializer lists of int values;</li>
|
|
<li>specifying integral values exceeding the range of float to define initializer lists of float values;</li>
|
|
<li>specifying values of integral types of a wider range than the integral type that is specified for the initializer list, except if the specified values lie within the range of the initializer list’s integral type</li>
|
|
</ul>
|
|
<p>Some examples:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>initializer_list<span style="color:#f92672"><</span><span style="color:#66d9ef">int</span><span style="color:#f92672">></span> ii{ <span style="color:#ae81ff">1.2</span> }; <span style="color:#75715e">// 1.2 isn't an int value
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>initializer_list<span style="color:#f92672"><</span><span style="color:#66d9ef">unsigned</span><span style="color:#f92672">></span> iu{ <span style="color:#f92672">~</span><span style="color:#ae81ff">0ULL</span> }; <span style="color:#75715e">// unsigned long long doesn't fit
|
|
</span></span></span></code></pre></div><h4 id="3351-designated-initialization">
|
|
3.3.5.1: Designated initialization
|
|
<a class="anchor" href="#3351-designated-initialization">#</a>
|
|
</h4>
|
|
<p>C++, like C, also supports designated initialization. However, as C++ requires that destruction of data members occurs in the opposite order as their construction it is required that, when using designated initialization, members are initialized in the order in which they are declared in their class or struct. E.g.,</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">Data</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> d_first;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">double</span> d_second;
|
|
</span></span><span style="display:flex;"><span> std<span style="color:#f92672">::</span>string d_third;
|
|
</span></span><span style="display:flex;"><span>};
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span>Data data{ .d_first <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>, .d_third <span style="color:#f92672">=</span> <span style="color:#e6db74">"hello"</span> };
|
|
</span></span></code></pre></div><p>In this example, <code>d_first</code> and <code>d_third</code> are explicitly initialized, while <code>d_second</code> is implicitly initialized to its default value (so: 0.0).</p>
|
|
<p>In C++ it is not allowed to reorder the initialization of members in a desginated initialization list. So, <code>Data data{ .d_third = "hello", .d_first = 1 }</code> is an error, but <code>Data data{ .d_third = "hello" }</code> is OK, as there is no ordering conflict in the latter example (this also initializes <code>d_first</code> and <code>d_second</code> to 0).</p>
|
|
<p>Likewise, a union can be initialized using designated initialization, as illustrated by the next example:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">union</span> <span style="color:#a6e22e">Data</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> d_first;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">double</span> d_second;
|
|
</span></span><span style="display:flex;"><span> std<span style="color:#f92672">::</span>string <span style="color:#f92672">*</span>d_third;
|
|
</span></span><span style="display:flex;"><span>};
|
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// initialize the union's d_third field:
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>Data data{ .d_third <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> string{ <span style="color:#e6db74">"hello"</span> } };
|
|
</span></span></code></pre></div><h3 id="336-initializers-for-bit-fields">
|
|
3.3.6: Initializers for bit-fields
|
|
<a class="anchor" href="#336-initializers-for-bit-fields">#</a>
|
|
</h3>
|
|
<p><strong>Bit-fields</strong> are used to specify series of bits in an integral value type. For example, in networking software processing IP4 packets, the first <code>uint32_t</code> value of IP4 packets contain:</p>
|
|
<ul>
|
|
<li>the version (4 bits);</li>
|
|
<li>the header length (4 bits);</li>
|
|
<li>the type of service (8 bits);</li>
|
|
<li>the total length (16 bits)</li>
|
|
</ul>
|
|
<p>Rather than using complex bit and bit-shift operations, these fields inside integral values can be specified using bit-fields. E.g.,</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">FirstIP4word</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">uint32_t</span> version: <span style="color:#ae81ff">4</span>;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">uint32_t</span> header: <span style="color:#ae81ff">4</span>;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">uint32_t</span> tos: <span style="color:#ae81ff">8</span>;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">uint32_t</span> length: <span style="color:#ae81ff">16</span>;
|
|
</span></span><span style="display:flex;"><span>};
|
|
</span></span></code></pre></div><p>To total size of a <code>FirstIP4word</code> object is 32 bits, or four bytes. To show the version of a <code>FirstIP4word</code> first object, simply do:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>cout <span style="color:#f92672"><<</span> first.version <span style="color:#f92672"><<</span> <span style="color:#e6db74">'\n'</span>;
|
|
</span></span></code></pre></div><p>and to set its header length to 10 simply do</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>first.header <span style="color:#f92672">=</span> <span style="color:#ae81ff">10</span>;
|
|
</span></span></code></pre></div><p>Bit fields are already available in C. The C++23 standard allows them to be initialized by default by using initialization expressions in their definitions. E.g.,</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">FirstIP4word</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">uint32_t</span> version: <span style="color:#ae81ff">4</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>; <span style="color:#75715e">// version now 1, by default
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#66d9ef">uint32_t</span> header: <span style="color:#ae81ff">4</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">10</span>; <span style="color:#75715e">// TCP header length now 10, by default
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#66d9ef">uint32_t</span> tos: <span style="color:#ae81ff">8</span>;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">uint32_t</span> length: <span style="color:#ae81ff">16</span>;
|
|
</span></span><span style="display:flex;"><span>};
|
|
</span></span></code></pre></div><p>The initialization expressions are evaluated when the object using the bit-fields is defined. Also, when a variable is used to initialize a bit-field the variable must at least have been declared when the struct containing bit-fields is defined. E.g.,</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">extern</span> <span style="color:#66d9ef">int</span> value;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">FirstIP4word</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> ...
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">uint32_t</span> length: <span style="color:#ae81ff">16</span> <span style="color:#f92672">=</span> value; <span style="color:#75715e">// OK: value has been declared
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>};
|
|
</span></span></code></pre></div><h3 id="337-type-inference-using-auto">
|
|
3.3.7: Type inference using <strong>auto</strong>
|
|
<a class="anchor" href="#337-type-inference-using-auto">#</a>
|
|
</h3>
|
|
<p>The keyword <code>auto</code> can be used to simplify type definitions of variables and return types of functions if the compiler is able to determine the proper types of such variables or functions.</p>
|
|
<p>Using <code>auto</code> as a storage class specifier is no longer supported by C++: a variable definition like <code>auto int</code> var results in a compilation error.</p>
|
|
<p>The keyword <code>auto</code> is used in situations where it is very hard to determine the variable’s type. These situations are encountered, e.g., in the context of templates (cf. chapters
|
|
<a href="/cpp/">18</a> until
|
|
<a href="/cpp/">23</a>). It is also used in situations where a known type is a very long one but also automatically available to the compiler. In such cases the programmer uses <code>auto</code> to avoid having to type long type definitions.</p>
|
|
<p>At this point in the Annotations only simple examples can be given. Refer to section 21.1.2 for additional information about auto (and the related decltype function).</p>
|
|
<p>When defining and initializing a variable <code>int variable = 5</code> the type of the initializing expression is well known: it’s an int, and unless the programmer’s intentions are different this could be used to define variable’s type (a somewhat contrived example as in this case it reduces rather than improves the clarity of the code):</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">auto</span> variable <span style="color:#f92672">=</span> <span style="color:#ae81ff">5</span>;
|
|
</span></span></code></pre></div><p>However, it is attractive to use <code>auto</code>. In chapter
|
|
<a href="/cpp/">5</a> the iterator concept is introduced (see also chapters
|
|
<a href="/cpp/">12</a> and
|
|
<a href="/cpp/">18</a>). Iterators frequently have long type definitions, like</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>std<span style="color:#f92672">::</span>vector<span style="color:#f92672"><</span>std<span style="color:#f92672">::</span>string<span style="color:#f92672">>::</span>const_reverse_iterator
|
|
</span></span></code></pre></div><p>Functions may return objects having such types. Since the compiler knows about these types we may exploit this knowledge by using <code>auto</code>. Assume that a function <code>begin()</code> is declared like this:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>std<span style="color:#f92672">::</span>vector<span style="color:#f92672"><</span>std<span style="color:#f92672">::</span>string<span style="color:#f92672">>::</span>const_reverse_iterator begin();
|
|
</span></span></code></pre></div><p>Rather than writing a long variable definition (at <code>// 1</code>, below) a much shorter definition (at <code>// 2</code>) can be used:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>std<span style="color:#f92672">::</span>vector<span style="color:#f92672"><</span>std<span style="color:#f92672">::</span>string<span style="color:#f92672">>::</span>const_reverse_iterator iter <span style="color:#f92672">=</span> begin(); <span style="color:#75715e">// 1
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">auto</span> iter <span style="color:#f92672">=</span> begin(); <span style="color:#75715e">// 2
|
|
</span></span></span></code></pre></div><p>It’s also easy to define and initialize additional variables of such types. When initializing such variables iter can be used to initialize those variables, and auto can be used, so the compiler deduces their types:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">auto</span> start <span style="color:#f92672">=</span> iter;
|
|
</span></span></code></pre></div><p>When defining variables using auto the variable’s type is deduced from the variable’s initializing expression. Plain types and pointer types are used as-is, but when the initializing expression is a reference type, then the reference’s basic type (without the reference, omitting <code>const</code> or <code>volatile</code> specifications) is used.</p>
|
|
<p>If a reference type is required then <code>auto &</code> or <code>auto &&</code> can be used. Likewise, <code>const</code> and/or <code>pointer</code> specifications can be used in combination with the <code>auto</code> keyword itself. Here are some examples:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> value;
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">auto</span> another <span style="color:#f92672">=</span> value; <span style="color:#75715e">// 'int another' is defined
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span>string <span style="color:#66d9ef">const</span> <span style="color:#f92672">&</span>text();
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">auto</span> str <span style="color:#f92672">=</span> text(); <span style="color:#75715e">// text's plain type is string, so
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#75715e">// string str, NOT string const str
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#75715e">// is defined
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>str <span style="color:#f92672">+=</span> <span style="color:#e6db74">"..."</span>; <span style="color:#75715e">// so, this is OK
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#f92672">*</span>ip <span style="color:#f92672">=</span> <span style="color:#f92672">&</span>value;
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">auto</span> ip2 <span style="color:#f92672">=</span> ip; <span style="color:#75715e">// int *ip2 is defined.
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> <span style="color:#f92672">&</span>ptr <span style="color:#f92672">=</span> ip;
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">auto</span> ip3 <span style="color:#f92672">=</span> ptr; <span style="color:#75715e">// int *ip3 is defined, omitting const &
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">auto</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">&</span>ip4 <span style="color:#f92672">=</span> ptr; <span style="color:#75715e">// int *const &ip4 is defined.
|
|
</span></span></span></code></pre></div><p>In the next to last <code>auto</code> specification, the tokens (reading right to left) from the reference to the basic type are omitted: here const & was appended to ptr’s basic type (<code>int *</code>). Hence, <code>int *ip2</code> is defined.</p>
|
|
<p>In the last <code>auto</code> specification auto also produces <code>int *</code>, but in the type definition <code>const &</code> is added to the type produced by <code>auto</code>, so <code>int *const &ip4</code> is defined.</p>
|
|
<p>The <code>auto</code> keyword can also be used to postpone the definition of a function’s return type. The declaration of a function intArrPtr returning a pointer to arrays of 10 ints looks like this:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> (<span style="color:#f92672">*</span>intArrPtr())[<span style="color:#ae81ff">10</span>];
|
|
</span></span></code></pre></div><p>Such a declaration is fairly complex. E.g., among other complexities it requires <strong>protection of the pointer</strong> using parentheses in combination with the function’s parameter list. In situations like these the specification of the return type can be postponed using the auto return type, followed by the specification of the function’s return type after any other specification the function might receive (e.g., as a const member (cf. section
|
|
<a href="/cpp/">7.7</a>) or following its <code>noexcept</code> specification (cf. section
|
|
<a href="/cpp/">23.8</a>)).</p>
|
|
<p>Using <code>auto</code> to declare the above function, the declaration becomes:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">auto</span> <span style="color:#a6e22e">intArrPtr</span>() <span style="color:#f92672">-></span> <span style="color:#66d9ef">int</span> (<span style="color:#f92672">*</span>)[<span style="color:#ae81ff">10</span>];
|
|
</span></span></code></pre></div><p>A return type specification using <code>auto</code> is called a late-specified return type.</p>
|
|
<p>Since the C++14 standard late return type specifications are no longer required for functions returning <code>auto</code>. Such functions can now simply be declared like this:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">auto</span> <span style="color:#a6e22e">autoReturnFunction</span>();
|
|
</span></span></code></pre></div><p>In this case some restrictions apply, both to the function definitions and the function declarations:</p>
|
|
<ul>
|
|
<li>If multiple return statements are used in function definitions they all must return values of identical types;</li>
|
|
<li>Functions merely returning <code>auto</code> cannot be used before the compiler has seen their definitions. So they cannot be used after mere declarations;</li>
|
|
<li>When functions returning <code>auto</code> are implemented as recursive function then at least one return statement must have been seen before the recursive call. E.g.,</li>
|
|
</ul>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">auto</span> <span style="color:#a6e22e">fibonacci</span>(size_t n)
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> (n <span style="color:#f92672"><=</span> <span style="color:#ae81ff">1</span>)
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> n;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> fibonacci(n <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>) <span style="color:#f92672">+</span> fibonacci(n <span style="color:#f92672">-</span> <span style="color:#ae81ff">2</span>);
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><h4 id="3371-structured-binding-declarations">
|
|
3.3.7.1: Structured binding declarations
|
|
<a class="anchor" href="#3371-structured-binding-declarations">#</a>
|
|
</h4>
|
|
<p>Usually functions return single-valued results: <code>doubles</code>, <code>ints</code>, <code>strings</code>, etc. When functions need to return multiple values a return by argument construction is often used, where addresses of variables that live outside of the called function are passed to functions, allowing the functions to assign new values to those variables.</p>
|
|
<p>When multiple values should be returned from a function a struct can be used, but pairs (cf. section
|
|
<a href="/cpp/">12.2</a>) or tuples (cf. section
|
|
<a href="/cpp/">22.6</a>) can also be used. Here’s a simple example, where a function fun returns a struct having two data fields:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">Return</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> first;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">double</span> second;
|
|
</span></span><span style="display:flex;"><span>};
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span>Return <span style="color:#a6e22e">fun</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> Return{ <span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">12.5</span> };
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>(Briefly forward referencing to sections
|
|
<a href="/cpp/">12.2</a> and
|
|
<a href="/cpp/">22.6</a>: the struct definition can completely be omitted if fun returns a pair or tuple. In those cases the following code remains valid.)</p>
|
|
<p>A function calling fun traditionally defines a variable of the same type as <code>fun</code>’s return type, and then uses that variable’s fields to access <code>first</code> and <code>second</code>. If you don’t like the typing, <code>auto</code> can also be used:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">auto</span> r1 <span style="color:#f92672">=</span> fun();
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> r1.first;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>Instead of referring to the elements of the returned <code>struct</code>, <code>pair</code> or <code>tuple</code> structured binding declarations can also be used. Here, <code>auto</code> is followed by a (square brackets surrounded) comma-separated list of variables, where each variable is defined, and receives the value of the corresponding field or element of the called function’s return value. So, the above <code>main</code> function can also be written like this:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">auto</span> [one, two] <span style="color:#f92672">=</span> fun();
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> one; <span style="color:#75715e">// one and two: now defined
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
|
|
</span></span></code></pre></div><p>Merely specifying <code>auto</code> results in <code>fun</code>’s return value being copied, and the structured bindings variables will refer to the copied value. But structured binding declarations can also be used in combination with (lvalue/rvalue) return values. The following ensures that <code>rone</code> and <code>rtwo</code> refer to the elements of <code>fun</code>’s anonymous return value:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">auto</span> <span style="color:#f92672">&&</span>[rone, rtwo] <span style="color:#f92672">=</span> fun();
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>If the called function returns a value that survives the function call itself, then structured binding declarations can use lvalue references. E.g.,</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>Return <span style="color:#f92672">&</span>fun2()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">static</span> Return ret{ <span style="color:#ae81ff">4</span>, <span style="color:#ae81ff">5</span> };
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> ret;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">auto</span> <span style="color:#f92672">&</span>[lone, ltwo] <span style="color:#f92672">=</span> fun2(); <span style="color:#75715e">// OK: referring to ret's fields
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
|
|
</span></span></code></pre></div><p>To use structured binding declarations it is not required to use function calls. The object providing the data can also anonymously be defined:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">auto</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">&</span>[lone, ltwo] <span style="color:#f92672">=</span> Return{ <span style="color:#ae81ff">4</span>, <span style="color:#ae81ff">5</span> };
|
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// or:
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#66d9ef">auto</span> <span style="color:#f92672">&&</span>[lone, ltwo] <span style="color:#f92672">=</span> Return{ <span style="color:#ae81ff">4</span>, <span style="color:#ae81ff">5</span> };
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>The object doesn’t even have to make its data members publicly available. In section <code>TUPLES</code> using structured bindings not necessarily referring to data members is covered.</p>
|
|
<p>Another application is found in situations where nested statements of for or selection statements benefit from using locally defined variables of various types. Such variables can easily be defined using structured binding declarations that are initialized from anonymous structs, pairs or tuples. Here is an example illustrating this:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">// define a struct:
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">Three</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> size_t year;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">double</span> firstAmount;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">double</span> interest;
|
|
</span></span><span style="display:flex;"><span>};
|
|
</span></span><span style="display:flex;"><span><span style="color:#75715e">// define an array of Three objects, and process each in turn:
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>Three array[<span style="color:#ae81ff">10</span>];
|
|
</span></span><span style="display:flex;"><span>fill(array); <span style="color:#75715e">// not implemented here
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">auto</span> <span style="color:#f92672">&</span>[year, amount, interest]<span style="color:#f92672">:</span> array)
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"Year "</span> <span style="color:#f92672"><<</span> year <span style="color:#f92672"><<</span> <span style="color:#e6db74">": amount = "</span> <span style="color:#f92672"><<</span> amount <span style="color:#f92672"><<</span> <span style="color:#e6db74">'\n'</span>;
|
|
</span></span></code></pre></div><p>When using structured bindings the structured binding declaration must specify all elements that are available. So if a struct has four data members the structured binding declaration must define four elements. To avoid warnings of unused variables at lease one of the variables of the structured binding declaration must be used.</p>
|
|
<h3 id="338-defining-types-and-using-declarations">
|
|
3.3.8: Defining types and <strong>using</strong> declarations
|
|
<a class="anchor" href="#338-defining-types-and-using-declarations">#</a>
|
|
</h3>
|
|
<p>In C++ <code>typedef</code> is commonly used to define shorthand notations for complex types. Assume we want to define a shorthand for a pointer to a function expecting a <code>double</code> and an <code>int</code>, and returning an <code>unsigned long long int</code>. Such a function could be:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">long</span> <span style="color:#66d9ef">long</span> <span style="color:#66d9ef">int</span> <span style="color:#a6e22e">compute</span>(<span style="color:#66d9ef">double</span>, <span style="color:#66d9ef">int</span>);
|
|
</span></span></code></pre></div><p>A pointer to such a function has the following form:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">long</span> <span style="color:#66d9ef">long</span> <span style="color:#a6e22e">int</span> (<span style="color:#f92672">*</span>pf)(<span style="color:#66d9ef">double</span>, <span style="color:#66d9ef">int</span>);
|
|
</span></span></code></pre></div><p>If this kind of pointer is frequently used, consider defining it using <code>typedef</code>: simply put <code>typedef</code> in front of it and the pointer’s name is turned into the name of a type. It could be capitalized to let it stand out more clearly as the name of a type:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">long</span> <span style="color:#66d9ef">long</span> <span style="color:#a6e22e">int</span> (<span style="color:#f92672">*</span>PF)(<span style="color:#66d9ef">double</span>, <span style="color:#66d9ef">int</span>);
|
|
</span></span></code></pre></div><p>After having defined this type, it can be used to declare or define such pointers:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>PF pf <span style="color:#f92672">=</span> compute; <span style="color:#75715e">// initialize the pointer to a function like
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#75715e">// 'compute'
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">fun</span>(PF pf); <span style="color:#75715e">// fun expects a pointer to a function like
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#75715e">// 'compute'
|
|
</span></span></span></code></pre></div><p>However, including the pointer in the <code>typedef</code> might not be a very good idea, as it masks the fact that <code>pf</code> is a pointer. After all, <code>PF pf</code> looks more like <code>int x</code> than <code>int *x</code>. To document that <code>pf</code> is in fact a pointer, slightly change the <code>typedef</code>:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">long</span> <span style="color:#66d9ef">long</span> <span style="color:#66d9ef">int</span> <span style="color:#a6e22e">FUN</span>(<span style="color:#66d9ef">double</span>, <span style="color:#66d9ef">int</span>);
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span>FUN <span style="color:#f92672">*</span>pf <span style="color:#f92672">=</span> compute; <span style="color:#75715e">// now pf clearly is a pointer.
|
|
</span></span></span></code></pre></div><p>The scope of <code>typedefs</code> is restricted to compilation units. Therefore, <code>typedefs</code> are usually embedded in header files which are then included by multiple source files in which the <code>typedefs</code> should be used.</p>
|
|
<p>In addition to <code>typedef</code> C++ offers the <code>using</code> keyword to associate a type and an identifier. In practice <code>typedef</code> and <code>using</code> can be used interchangeably. The using keyword arguably result in more readable type definitions. Consider the following three (equivalent) definitions:</p>
|
|
<ul>
|
|
<li>
|
|
<p>The traditional, C style definition of a type, embedding the type name in the definition (turning a variable name into a type name):</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">long</span> <span style="color:#66d9ef">long</span> <span style="color:#66d9ef">int</span> <span style="color:#a6e22e">FUN</span>(<span style="color:#66d9ef">double</span>, <span style="color:#66d9ef">int</span>);
|
|
</span></span></code></pre></div></li>
|
|
<li>
|
|
<p>Apply using to improve the visibility (for humans) of the type name, by moving the type name to the front of the definition:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">using</span> FUN <span style="color:#f92672">=</span> <span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">long</span> <span style="color:#66d9ef">long</span> <span style="color:#66d9ef">int</span> (<span style="color:#66d9ef">double</span>, <span style="color:#66d9ef">int</span>);
|
|
</span></span></code></pre></div></li>
|
|
<li>
|
|
<p>An alternative construction, using a late-specified return type (cf. section
|
|
<a href="/cpp/docs/A-First-Impression/#337-type-inference-using-auto">3.3.7</a>):</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">using</span> FUN <span style="color:#f92672">=</span> <span style="color:#66d9ef">auto</span> (<span style="color:#66d9ef">double</span>, <span style="color:#66d9ef">int</span>) <span style="color:#f92672">-></span> <span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">long</span> <span style="color:#66d9ef">long</span> <span style="color:#66d9ef">int</span>;
|
|
</span></span></code></pre></div></li>
|
|
</ul>
|
|
<h3 id="339-range-based-for-loops">
|
|
3.3.9: Range-based for-loops
|
|
<a class="anchor" href="#339-range-based-for-loops">#</a>
|
|
</h3>
|
|
<p>The C++ for-statement is identical to C’s for-statement:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (init; cond; inc)
|
|
</span></span><span style="display:flex;"><span> statement
|
|
</span></span></code></pre></div><p>Often the initialization, condition, and increment parts are fairly obvious, as in situations where all elements of an array or vector must be processed. Many languages offer the <code>foreach</code> statement for that and C++ offers the <code>std::for_each</code> generic algorithm (cf. section
|
|
<a href="/cpp/">19.1.18</a>).</p>
|
|
<p>In addition to the traditional syntax C++ adds new syntax for the for-statement: the range-based for-loop. This new syntax can be used to process all element of a range in turn. Three types of ranges are distinguished:</p>
|
|
<ul>
|
|
<li>Plain arrays (e.g., <code>int array[10]</code>);</li>
|
|
<li>Initializer lists;</li>
|
|
<li>Standard containers (or comparable) (cf. chapter
|
|
<a href="/cpp/">12</a>);</li>
|
|
<li>Any other type offering <code>begin()</code> and <code>end()</code> functions returning so-called iterators (cf. section
|
|
<a href="/cpp/">18.2</a>).</li>
|
|
</ul>
|
|
<p>The following additional for-statement syntax is available:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">// assume int array[30]
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">auto</span> <span style="color:#f92672">&</span>element: array)
|
|
</span></span><span style="display:flex;"><span> statement
|
|
</span></span></code></pre></div><p>The part to the left of the colon is called the for range declaration. The declared variable (<code>element</code>) is a formal name; use any identifier you like. The variable is only available within the nested statement, and it refers to (or is a copy of) each of the elements of the range, from the first element up to the last.</p>
|
|
<p>There’s no formal requirement to use <code>auto</code>, but using <code>auto</code> is extremely useful in many situations. Not only in situations where the range refers to elements of some complex type, but also in situations where you know what you can do with the elements in the range, but don’t care about their exact type names. In the above example int could also have been used.</p>
|
|
<p>The reference symbol (&) is important in the following cases:</p>
|
|
<ul>
|
|
<li>if you want to modify the elements in the nested statements</li>
|
|
<li>if the elements themselves are structs (or classes, cf. chapter
|
|
<a href="/cpp/">7</a>)</li>
|
|
</ul>
|
|
<p>When the reference symbol is omitted the variable will be a copy of each of the subsequent elements of the range. Fine, probably, if you merely need to look at the variables when they are of primitive types, but needlessly inefficient if you have an array of <code>BigStruct</code> elements:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">BigStruct</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">double</span> array[<span style="color:#ae81ff">100</span>];
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> last;
|
|
</span></span><span style="display:flex;"><span>};
|
|
</span></span></code></pre></div><p>Inefficient, because you don’t need to make copies of the array’s elements. Instead, use references to elements:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>BigStruct data[<span style="color:#ae81ff">100</span>]; <span style="color:#75715e">// assume properly initialized elsewhere
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">countUsed</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">int</span> sum <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// const &: the elements aren't modified
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">auto</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">&</span>element: data)
|
|
</span></span><span style="display:flex;"><span> sum <span style="color:#f92672">+=</span> element.last;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> sum;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>Range-based for-loops can also benefit from structured bindings. If struct <code>Element</code> holds a int <code>key</code> and a double <code>value</code>, and all the values of positive keys should be added then the following code snippet accomplishes that:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>Element elems[<span style="color:#ae81ff">100</span>]; <span style="color:#75715e">// somehow initialized
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">double</span> sum <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">auto</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">&</span>[key, value]<span style="color:#f92672">:</span> elems)
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> (key <span style="color:#f92672">></span> <span style="color:#ae81ff">0</span>)
|
|
</span></span><span style="display:flex;"><span> sum <span style="color:#f92672">+=</span> value;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>The C++23 standard also supports an optional initialization section (like the ones already available for if and switch statements) for range-based for-loops. Assume the elements of an array must be inserted into <code>cout</code>, but before each element we want to display the element’s index. The index variable is not used outside the for-statement, and the extension offered in the C++23 standard allows us to localize the index variable. Here is an example:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">// localize idx: only visible in the for-stmnt
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">for</span> (size_t idx <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#66d9ef">auto</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">&</span>element: data)
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> idx<span style="color:#f92672">++</span> <span style="color:#f92672"><<</span> <span style="color:#e6db74">": "</span> <span style="color:#f92672"><<</span> element <span style="color:#f92672"><<</span> <span style="color:#e6db74">'\n'</span>;
|
|
</span></span></code></pre></div><h3 id="3310-raw-string-literals">
|
|
3.3.10: Raw String Literals
|
|
<a class="anchor" href="#3310-raw-string-literals">#</a>
|
|
</h3>
|
|
<p>Standard series of ASCII characters (a.k.a. C strings) are delimited by double quotes, supporting escape sequences like <code>\n</code>, <code>\\</code> and <code>\"</code>, and ending in 0-bytes. Such series of ASCII-characters are commonly known as null-terminated byte strings (singular: <code>NTBS</code>, plural: <code>NTBSs</code>). C’s <code>NTBS</code> is the foundation upon which an enormous amount of code has been built</p>
|
|
<p>In some cases it is attractive to be able to avoid having to use escape sequences (e.g., in the context of <code>XML</code>). C++ allows this using raw string literals.</p>
|
|
<p>Raw string literals start with an <code>R</code>, followed by a double quote, optionally followed by a label (which is an arbitrary sequence of non-blank characters, followed by <code>()</code>. The raw string ends at the closing parenthesis ), followed by the label (if specified when starting the raw string literal), which is in turn followed by a double quote. Here are some examples:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>R<span style="color:#e6db74">"(A Raw \ "</span>String<span style="color:#e6db74">")"</span>
|
|
</span></span><span style="display:flex;"><span>R<span style="color:#e6db74">"delimiter(Another \ Raw "</span>(String))delimiter<span style="color:#e6db74">"</span>
|
|
</span></span></code></pre></div><p>In the first case, everything between <code>"( and )"</code> is part of the string. Escape sequences aren’t supported so the text <code>\ "</code> within the first raw string literal defines three characters: a backslash, a blank character and a double quote. The second example shows a raw string defined between the markers <code>"delimiter( and )delimiter"</code>.</p>
|
|
<p>Raw string literals come in very handy when long, complex ascii-character sequences (e.g., <code>usage-info</code> or long <code>html-sequences</code>) are used. In the end they are just that: long NTBSs. Those long raw string literals should be separated from the code that uses them, thus maintaining the readability of the using code.</p>
|
|
<p>As an illustration: the <code>bisonc++</code> parser generator supports an option <code>--prompt</code>. When specified, the code generated by <code>bisonc++</code> inserts prompting code when debugging is requested. Directly inserting the raw string literal into the function processing the prompting code results in code that is very hard to read:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">prompt</span>(ostream <span style="color:#f92672">&</span>out)
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> (d_genDebug)
|
|
</span></span><span style="display:flex;"><span> out <span style="color:#f92672"><<</span> (d_options.prompt() <span style="color:#f92672">?</span> R<span style="color:#e6db74">"(</span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> (d_debug__)
|
|
</span></span><span style="display:flex;"><span> {
|
|
</span></span><span style="display:flex;"><span> s_out__ <span style="color:#f92672"><<</span> <span style="color:#e6db74">"</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">================</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">"</span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">"? "</span> <span style="color:#f92672"><<</span> dflush__;
|
|
</span></span><span style="display:flex;"><span> std<span style="color:#f92672">::</span>string s;
|
|
</span></span><span style="display:flex;"><span> getline(std<span style="color:#f92672">::</span>cin, s);
|
|
</span></span><span style="display:flex;"><span> }
|
|
</span></span><span style="display:flex;"><span>)<span style="color:#e6db74">" : R"</span>(
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> (d_debug__)
|
|
</span></span><span style="display:flex;"><span> s_out__ <span style="color:#f92672"><<</span> <span style="color:#e6db74">'\n'</span>;
|
|
</span></span><span style="display:flex;"><span>)<span style="color:#e6db74">"</span>
|
|
</span></span><span style="display:flex;"><span> ) <span style="color:#f92672"><<</span> <span style="color:#e6db74">'\n'</span>;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><p>Readability is greatly enhanced by defining the raw string literals as named NTBSs, defined in the source file’s anonymous namespace (cf. chapter
|
|
<a href="/cpp/docs/Name-Spaces/">4</a>):</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">namespace</span> {
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> noPrompt[] <span style="color:#f92672">=</span>
|
|
</span></span><span style="display:flex;"><span>R<span style="color:#e6db74">"(</span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> (d_debug__)
|
|
</span></span><span style="display:flex;"><span> s_out__ <span style="color:#f92672"><<</span> <span style="color:#e6db74">'\n'</span>;
|
|
</span></span><span style="display:flex;"><span>)<span style="color:#e6db74">";</span>
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> doPrompt[] <span style="color:#f92672">=</span>
|
|
</span></span><span style="display:flex;"><span>R<span style="color:#e6db74">"(</span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> (d_debug__)
|
|
</span></span><span style="display:flex;"><span> {
|
|
</span></span><span style="display:flex;"><span> s_out__ <span style="color:#f92672"><<</span> <span style="color:#e6db74">"</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">================</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">"</span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">"? "</span> <span style="color:#f92672"><<</span> dflush__;
|
|
</span></span><span style="display:flex;"><span> std<span style="color:#f92672">::</span>string s;
|
|
</span></span><span style="display:flex;"><span> getline(std<span style="color:#f92672">::</span>cin, s);
|
|
</span></span><span style="display:flex;"><span> }
|
|
</span></span><span style="display:flex;"><span>)<span style="color:#e6db74">";</span>
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span>} <span style="color:#75715e">// anonymous namespace
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">prompt</span>(ostream <span style="color:#f92672">&</span>out)
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> (d_genDebug)
|
|
</span></span><span style="display:flex;"><span> out <span style="color:#f92672"><<</span> (d_options.prompt() <span style="color:#f92672">?</span> doPrompt : noPrompt) <span style="color:#f92672"><<</span> <span style="color:#e6db74">'\n'</span>;
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div><h3 id="3311-binary-constants">
|
|
3.3.11: Binary constants
|
|
<a class="anchor" href="#3311-binary-constants">#</a>
|
|
</h3>
|
|
<p>In addition to hexadecimal integral constants (starting with <code>0x</code>), octal integral constants (starting with <code>0</code>), and decimal integral constants (starting with one of the digits 1..9), binary integral constants can be defined using the prefixes <code>0b</code> or <code>0B</code>. E.g., to represent the (decimal) value <code>5</code> the notation <code>0b101</code> can also be used.</p>
|
|
<p>The binary constants come in handy in the context of, e.g., bit-flags, as it immediately shows which bit-fields are set, while other notations are less informative.</p>
|
|
<h3 id="3312-selection-statements-with-initializers">
|
|
3.3.12: Selection statements with initializers
|
|
<a class="anchor" href="#3312-selection-statements-with-initializers">#</a>
|
|
</h3>
|
|
<p>The standard for repetition statements start with an optional initialization clause. The initialization clause allows us to localize variables to the scope of the for statements. Initialization clauses van also be used in selection statements.</p>
|
|
<p>Consider the situation where an action should be performed if the next line read from the standard input stream equals go!. Traditionally, when used inside a function, intending to localize the string to contain the content of the next line as much as possible, constructions like the following had to be used:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">function</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// ... any set of statements
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> {
|
|
</span></span><span style="display:flex;"><span> string line; <span style="color:#75715e">// localize line
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#66d9ef">if</span> (getline(cin, line))
|
|
</span></span><span style="display:flex;"><span> action();
|
|
</span></span><span style="display:flex;"><span> }
|
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// ... any set of statements
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
|
|
</span></span></code></pre></div><p>Since init ; clauses can also be used for selection statements (if and switch statements) (note that with selection statements the semicolon is part of the initialization clause, which is different from the optional init (no semicolon) clause in for statements), we can rephrase the above example as follows:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">function</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// ... any set of statements
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#66d9ef">if</span> (string line; getline(cin, line))
|
|
</span></span><span style="display:flex;"><span> action();
|
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// ... any set of statements
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
|
|
</span></span></code></pre></div><p>Note that a variable may still also be defined in the actual condition clauses. This is true for both the extended if and switch statement. However, before using the condition clauses an initialization clause may be used to define additional variables (plural, as it may contain a comma-separated list of variables, similar to the syntax that’s available for for-statements).</p>
|
|
<h3 id="3313-attributes">
|
|
3.3.13: Attributes
|
|
<a class="anchor" href="#3313-attributes">#</a>
|
|
</h3>
|
|
<p>Attributes are compiler directives that are inserted into source files to inform the compiler of some peculiarity of the code (variable or function) that follows the specified attribute. Attributes are used to inform the compiler about situations that are intentional, and thus prevent the compiler from issuing warnings.</p>
|
|
<p>The following attributes are recognized:</p>
|
|
<ul>
|
|
<li>
|
|
<p><strong>[[carries_dependency]]</strong>:</p>
|
|
<p>This attribute is currently not yet covered by the C++ Annotations. At this point in the C++ Annotations it can safely be ignored.</p>
|
|
</li>
|
|
<li>
|
|
<p><strong>[[deprecated]]</strong>:</p>
|
|
<p>This attribute (and its alternative form <code>[[deprecated("reason")]]</code>) is available since the C++14 standard. It indicates that the use of the name or entity declared with this attribute is allowed, but discouraged for some reason. This attribute can be used for classes, typedef-names, variables, non-static data members, functions, enumerations, and template specializations. An existing non-deprecated entity may be redeclared deprecated, but once an entity has been declared deprecated it cannot be redeclared as <code>undeprecated'. When encountering the </code>[[deprecated]]` attribute the compiler generates a warning, e.g.,</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>demo.cc:12:24: warning: <span style="color:#e6db74">'void deprecatedFunction()'</span> is deprecated
|
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672">[</span>-Wdeprecated-declarations<span style="color:#f92672">]</span> deprecatedFunction<span style="color:#f92672">()</span>;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span>demo.cc:5:21: note: declared here
|
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672">[[</span>deprecated<span style="color:#f92672">]]</span> void deprecatedFunction<span style="color:#f92672">()</span>
|
|
</span></span></code></pre></div><p>When using the alternative form (e.g., <code>[[deprecated("do not use")]] void fun())</code> the compiler generates a warning showing the text between the double quotes, e.g.,</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>demo.cc:12:24: warning: <span style="color:#e6db74">'void deprecatedFunction()'</span> is deprecated:
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">do</span> not use <span style="color:#f92672">[</span>-Wdeprecated-declarations<span style="color:#f92672">]</span>
|
|
</span></span><span style="display:flex;"><span> deprecatedFunction<span style="color:#f92672">()</span>;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span>demo.cc:5:38: note: declared here
|
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672">[[</span>deprecated<span style="color:#f92672">(</span><span style="color:#e6db74">"do not use"</span><span style="color:#f92672">)]]</span> void deprecatedFunction<span style="color:#f92672">()</span>
|
|
</span></span></code></pre></div></li>
|
|
<li>
|
|
<p><strong>[[fallthrough]]</strong></p>
|
|
<p>When statements nested under case entries in switch statements continue into subsequent case or default entries the compiler issues a <code>falling through</code> warning. If falling through is intentional the attribute <code>[[fallthrough]]</code>, which then must be followed by a semicolon, should be used. Here is an annotated example:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">function</span>(<span style="color:#66d9ef">int</span> selector)
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">switch</span> (selector)
|
|
</span></span><span style="display:flex;"><span> {
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">case</span> <span style="color:#ae81ff">1</span><span style="color:#f92672">:</span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">case</span> <span style="color:#ae81ff">2</span><span style="color:#f92672">:</span> <span style="color:#75715e">// no falling through, but merged entry points
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"cases 1 and 2</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">"</span>;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">[[fallthrough]]</span>; <span style="color:#75715e">// no warning: intentionally falling through
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">case</span> <span style="color:#ae81ff">3</span><span style="color:#f92672">:</span>
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"case 3</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">"</span>;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">case</span> <span style="color:#ae81ff">4</span><span style="color:#f92672">:</span> <span style="color:#75715e">// a warning is issued: falling through not
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#75715e">// announced.
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"case 4</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">"</span>;
|
|
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">[[fallthrough]]</span>; <span style="color:#75715e">// error: there's nothing beyond
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> }
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div></li>
|
|
<li>
|
|
<p><strong>[[maybe_unused]]</strong></p>
|
|
<p>This attribute can be applied to a class, typedef-name, variable, parameter, non-static data member, a function, an enumeration or an enumerator. When it is applied to an entity no warning is generated when the entity is not used. Example:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">fun</span>(<span style="color:#a6e22e">[[maybe_unused]]</span> size_t argument)
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> <span style="color:#75715e">// argument isn't used, but no warning
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#75715e">// telling you so is issued
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
|
|
</span></span></code></pre></div></li>
|
|
<li>
|
|
<p><strong>[[nodiscard]]</strong></p>
|
|
<p>The attribute <code>[[nodiscard]]</code> may be specified when declaring a function, class or enumeration. If a function is declared <code>[[nodiscard]]</code> or if a function returns an entity previously declared using <code>[[nodiscard]]</code> then the return value of such a function may only be ignored when explicitly cast to void. Otherwise, when the return value is not used a warning is issued. Example:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">[[nodiscard]]</span> importantInt();
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">[[nodiscard]]</span> <span style="color:#a6e22e">ImportantStruct</span> { ... };
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span>ImportantStruct <span style="color:#a6e22e">factory</span>();
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> importantInt(); <span style="color:#75715e">// warning issued
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> factory(); <span style="color:#75715e">// warning issued
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}
|
|
</span></span></code></pre></div></li>
|
|
<li>
|
|
<p><strong>[[noreturn]]</strong>:</p>
|
|
<p><code>[[noreturn]]</code> indicates that the function does not return. <code>[noreturn]]</code>’s behavior is undefined if the function declared with this attribute actually returns. The following standard functions have this attribute: <code>std::_Exit</code>, <code>std::abort</code>, <code>std::exit</code>, <code>std::quick_exit</code>, <code>std::unexpected</code>, <code>std::terminate</code>, <code>std::rethrow_exception</code>, <code>std::throw_with_nested</code>, <code>std::nested_exception::rethrow_nested</code>, Here is an example of a function declaration and definition using the <code>[[noreturn]]</code> attribute:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#a6e22e">[[noreturn]]</span> <span style="color:#66d9ef">void</span> doesntReturn();
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">[[noreturn]]</span> <span style="color:#66d9ef">void</span> doesntReturn()
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> exit(<span style="color:#ae81ff">0</span>);
|
|
</span></span><span style="display:flex;"><span>}
|
|
</span></span></code></pre></div></li>
|
|
</ul>
|
|
<h3 id="3314-three-way-comparison-">
|
|
3.3.14: Three-way comparison (<=>)
|
|
<a class="anchor" href="#3314-three-way-comparison-">#</a>
|
|
</h3>
|
|
<p>The C++23 standard added the <strong>three-way comparison operator <=></strong>, also known as the spaceship operator, to C++. In C++ operators can be defined for class-types, among which equality and comparison operators (the familiar set of <code>==</code>, <code>!=</code>, <code><</code>, <code><=</code>, <code>></code> and <code>>=</code> operators). To provide classes with all comparison operators merely the the equality and the spaceship operator need to be defined.</p>
|
|
<p>Its priority is less than the priorities of the bit-shift operators <code><<</code> and <code>>></code> and larger than the priorities of the ordering operators <code><</code>, <code><=</code>, <code>></code>, and <code>>=</code>.</p>
|
|
<p>Section
|
|
<a href="/cpp/">11.7.2</a> covers the construction of the three-way comparison operator.</p>
|
|
<h2 id="34-new-language-defined-data-types">
|
|
3.4: New language-defined data types
|
|
<a class="anchor" href="#34-new-language-defined-data-types">#</a>
|
|
</h2>
|
|
<p>In C the following built-in data types are available: <code>void</code>, <code>char</code>, <code>short</code>, <code>int</code>, <code>long</code>, <code>float</code> and <code>double</code>. C++ extends these built-in types with several additional built-in types: the types <code>bool</code>, <code>wchar_t</code>, <code>long long</code> and <code>long double</code> (Cf. ANSI/ISO draft (1995), par. 27.6.2.4.1 for examples of these very long types). The type <code>long long</code> is merely a double-long long datatype. The type <code>long double</code> is merely a double-long double datatype. These built-in types as well as pointer variables are called primitive types in the C++ Annotations.</p>
|
|
<p>There is a subtle issue to be aware of when converting applications developed for 32-bit architectures to 64-bit architectures. When converting 32-bit programs to 64-bit programs, only long types and pointer types change in size from 32 bits to 64 bits; integers of type int remain at their size of 32 bits. This may cause data truncation when assigning pointer or long types to int types. Also, problems with sign extension can occur when assigning expressions using types shorter than the size of an int to an unsigned long or to a pointer. More information about this issue can be found
|
|
<a href="http://developers.sun.com/solaris/articles/ILP32toLP64Issues.html">here</a>.</p>
|
|
<p>Except for these built-in types the <code>class-type string</code> is available for handling character strings. The datatypes <code>bool</code>, and <code>wchar_t</code> are covered in the following sections, the datatype string is covered in chapter 5. Note that recent versions of C may also have adopted some of these newer data types (notably <code>bool</code> and <code>wchar_t</code>). Traditionally, however, C doesn’t support them, hence they are mentioned here.</p>
|
|
<p>Now that these new types are introduced, let’s refresh your memory about letters that can be used in literal constants of various types. They are:</p>
|
|
<ul>
|
|
<li><strong>b or B</strong>: in addition to its use as a hexadecimal value, it can also be used to define a binary constant. E.g., <code>0b101</code> equals the decimal value 5. The <code>0b</code> prefix can be used to specify binary constants starting with the C++14 standard.</li>
|
|
<li><strong>E or e</strong>: the exponentiation character in floating point literal values. For example: <code>1.23E+3</code>. Here, <code>E</code> should be pronounced (and interpreted) as: times 10 to the power. Therefore, <code>1.23E+3</code> represents the value 1230.</li>
|
|
<li><strong>F</strong> can be used as postfix to a non-integral numeric constant to indicate a value of type float, rather than double, which is the default. For example: <code>12.F</code> (the dot transforms 12 into a floating point value); <code>1.23E+3F</code> (see the previous example. <code>1.23E+3</code> is a double value, whereas <code>1.23E+3F</code> is a float value).</li>
|
|
<li><strong>L</strong> can be used as prefix to indicate a character string whose elements are wchar_t-type characters. For example: <code>L"hello world"</code>.</li>
|
|
<li><strong>L</strong> can be used as postfix to an integral value to indicate a value of type <code>long</code>, rather than <code>int</code>, which is the default. Note that there is no letter indicating a short type. For that a <code>static_cast<short>()</code> must be used.</li>
|
|
<li><strong>p</strong>, to specify the power in hexadecimal floating point numbers. E.g. <code>0x10p4</code>. The exponent itself is read as a decimal constant and can therefore not start with <code>0x</code>. The exponent part is interpreted as a power of 2. So <code>0x10p2</code> is (decimal) equal to 64: 16 * 2^2.</li>
|
|
<li><strong>U</strong> can be used as postfix to an integral value to indicate an <code>unsigned</code> value, rather than an <code>int</code>. It may also be combined with the postfix <code>L</code> to produce an <code>unsigned long int</code> value.</li>
|
|
</ul>
|
|
<p>And, of course: the <code>x</code> and a until <code>f</code> characters can be used to specify hexadecimal constants (optionally using capital letters).</p>
|
|
<h3 id="341-the-data-type-bool">
|
|
3.4.1: The data type <strong>bool</strong>
|
|
<a class="anchor" href="#341-the-data-type-bool">#</a>
|
|
</h3>
|
|
<p>The type bool represents boolean (logical) values, for which the (now reserved) constants true and false may be used. Except for these reserved values, integral values may also be assigned to variables of type bool, which are then implicitly converted to true and false according to the following conversion rules (assume <code>intValue</code> is an int-variable, and <code>boolValue</code> is a bool-variable):</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">// from int to bool:
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>boolValue <span style="color:#f92672">=</span> intValue <span style="color:#f92672">?</span> true <span style="color:#f92672">:</span> false;
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#75715e">// from bool to int:
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>intValue <span style="color:#f92672">=</span> boolValue <span style="color:#f92672">?</span> <span style="color:#ae81ff">1</span> <span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>;
|
|
</span></span></code></pre></div><p>Furthermore, when bool values are inserted into streams then true is represented by 1, and false is represented by 0. Consider the following example:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"A true value: "</span> <span style="color:#f92672"><<</span> true <span style="color:#f92672"><<</span> <span style="color:#e6db74">"</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">"</span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#e6db74">"A false value: "</span> <span style="color:#f92672"><<</span> false <span style="color:#f92672"><<</span> <span style="color:#e6db74">'\n'</span>;
|
|
</span></span></code></pre></div><p>The bool data type is found in other programming languages as well. <code>Pascal</code> has its type <code>Boolean</code>; <code>Java</code> has a <code>boolean</code> type. Different from these languages, C++’s type bool acts like a kind of int type. It is primarily a documentation-improving type, having just two values true and false. Actually, these values can be interpreted as enum values for 1 and 0. Doing so would ignore the philosophy behind the bool data type, but nevertheless: assigning true to an int variable neither produces warnings nor errors.</p>
|
|
<p>Using the bool-type is usually clearer than using int. Consider the following prototypes:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">bool</span> <span style="color:#a6e22e">exists</span>(<span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span>fileName); <span style="color:#75715e">// (1)
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">exists</span>(<span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span>fileName); <span style="color:#75715e">// (2)
|
|
</span></span></span></code></pre></div><p>With the first prototype, readers expect the function to return true if the given filename is the name of an existing file. However, with the second prototype some ambiguity arises: intuitively the return value 1 is appealing, as it allows constructions like</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (exists(<span style="color:#e6db74">"myfile"</span>))
|
|
</span></span><span style="display:flex;"><span> cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"myfile exists"</span>;
|
|
</span></span></code></pre></div><p>On the other hand, many system functions (like <code>access</code>, <code>stat</code>, and many other) return 0 to indicate a successful operation, reserving other values to indicate various types of errors.</p>
|
|
<p>As a rule of thumb I suggest the following: if a function should inform its caller about the success or failure of its task, let the function return a bool value. If the function should return success or various types of errors, let the function return enum values, documenting the situation by its various symbolic constants. Only when the function returns a conceptually meaningful integral value (like the sum of two int values), let the function return an int value.</p>
|
|
<h3 id="342-the-data-type-wchar_t">
|
|
3.4.2: The data type <strong>wchar_t</strong>
|
|
<a class="anchor" href="#342-the-data-type-wchar_t">#</a>
|
|
</h3>
|
|
<p>The <code>wchar_t</code> type is an extension of the char built-in type, to accommodate wide character values (but see also the next section). The g++ compiler reports <code>sizeof(wchar_t)</code> as 4, which easily accommodates all 65,536 different Unicode character values.</p>
|
|
<p>Note that Java’s char data type is somewhat comparable to C++’s <code>wchar_t</code> type. Java’s char type is 2 bytes wide, though. On the other hand, Java’s byte data type is comparable to C++’s char type: one byte. Confusing?</p>
|
|
<h3 id="343-unicode-encoding">
|
|
3.4.3: Unicode encoding
|
|
<a class="anchor" href="#343-unicode-encoding">#</a>
|
|
</h3>
|
|
<p>In C++ string literals can be defined as <code>NTBSs</code>. Prepending an <code>NTBS</code> by <code>L</code> (e.g., <code>L"hello"</code>) defines a wchar_t string literal.</p>
|
|
<p>C++ also supports 8, 16 and 32 bit Unicode encoded strings. Furthermore, two new data types are introduced: <code>char16_t</code> and <code>char32_t</code> storing, respectively, a <code>UTF-16</code> and a <code>UTF-32</code> unicode value.</p>
|
|
<p>A char type value fits in a utf_8 unicode value. For character sets exceeding 256 different values wider types (like <code>char16_t</code> or <code>char32_t</code>) should be used.</p>
|
|
<p>String literals for the various types of unicode encodings (and associated variables) can be defined as follows:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">char</span> utf_8[] <span style="color:#f92672">=</span> <span style="color:#e6db74">u8</span><span style="color:#e6db74">"This is UTF-8 encoded."</span>;
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">char16_t</span> utf16[] <span style="color:#f92672">=</span> <span style="color:#e6db74">u</span><span style="color:#e6db74">"This is UTF-16 encoded."</span>;
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">char32_t</span> utf32[] <span style="color:#f92672">=</span> <span style="color:#e6db74">U</span><span style="color:#e6db74">"This is UTF-32 encoded."</span>;
|
|
</span></span></code></pre></div><p>Alternatively, unicode constants may be defined using the <code>\u</code> escape sequence, followed by a hexadecimal value. Depending on the type of the unicode variable (or constant) a <code>UTF-8</code>, <code>UTF-16</code> or <code>UTF-32</code> value is used. E.g.,</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">char</span> utf_8[] <span style="color:#f92672">=</span> <span style="color:#e6db74">u8</span><span style="color:#e6db74">"</span><span style="color:#ae81ff">\u2018</span><span style="color:#e6db74">"</span>;
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">char16_t</span> utf16[] <span style="color:#f92672">=</span> <span style="color:#e6db74">u</span><span style="color:#e6db74">"</span><span style="color:#ae81ff">\u2018</span><span style="color:#e6db74">"</span>;
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">char32_t</span> utf32[] <span style="color:#f92672">=</span> <span style="color:#e6db74">U</span><span style="color:#e6db74">"</span><span style="color:#ae81ff">\u2018</span><span style="color:#e6db74">"</span>;
|
|
</span></span></code></pre></div><p>Unicode strings can be delimited by double quotes but raw string literals can also be used.</p>
|
|
<h3 id="344-the-data-type-long-long-int">
|
|
3.4.4: The data type <code>long long int</code>
|
|
<a class="anchor" href="#344-the-data-type-long-long-int">#</a>
|
|
</h3>
|
|
<p>C++ also supports the type <code>long long in</code>t. <strong>On 32 bit systems it has at least 64 usable bits</strong>.</p>
|
|
<h3 id="345-the-data-type-size_t">
|
|
3.4.5: The data type <strong>size_t</strong>
|
|
<a class="anchor" href="#345-the-data-type-size_t">#</a>
|
|
</h3>
|
|
<p>The <code>size_t</code> type is not really a built-in primitive data type, but a data type that is promoted by POSIX as a typename to be used for non-negative integral values answering questions like how much and how many, in which case it should be used instead of <code>unsigned int</code>. It is not a specific C++ type, but also available in, e.g., C. Usually it is defined implicitly when a (any) system header file is included. The header file <code>officially</code> defining <code>size_t</code> in the context of C++ is cstddef.</p>
|
|
<p>Using <code>size_t</code> has the advantage of being a conceptual type, rather than a standard type that is then modified by a modifier. Thus, it improves the self-documenting value of source code.</p>
|
|
<p>Several suffixes can be used to expicitly specify the intended representation of integral constants, like 42UL defining 42 as an unsigned long int. Likewise, suffixes uz or zu can be used to specify that an integral constant is represented as a <code>size_t</code>, as in: <code>cout << 42uz</code>.</p>
|
|
<p>Sometimes functions explictly require <code>unsigned int</code> to be used. E.g., on amd-architectures the X-windows function XQueryPointer explicitly requires a pointer to an <code>unsigned int</code> variable as one of its arguments. In such situations a pointer to a <code>size_t</code> variable can’t be used, but the address of an <code>unsigned int</code> must be provided. Such situations are exceptional, though.</p>
|
|
<p>Other useful bit-represented types also exists. E.g., <code>uint32_t</code> is guaranteed to hold 32-bits unsigned values. Analogously, <code>int32_t</code> holds 32-bits signed values. Corresponding types exist for 8, 16 and 64 bits values. These types are defined in the header file <code>cstdint</code> and can be very useful when you need to specify or use integral value types of fixed sizes.</p>
|
|
<h3 id="346-the-data-type-stdbyte">
|
|
3.4.6: The data type <strong>std::byte</strong>
|
|
<a class="anchor" href="#346-the-data-type-stdbyte">#</a>
|
|
</h3>
|
|
<p>Quite often 8-bit variables are required, usually to access memory locations. Traditionally the <code>char</code> type has been used for that, but <code>char</code> is a signed type and when inserting a char variable into a stream the character’s representation instead of its value is used. Maybe more important is the inherent confusion when using <code>char</code> type variables when only using its (unsigned) value: a char documents to the reader that text is used instead of mere 8-bit values, as used by the smallest addressable memory locations.</p>
|
|
<p>Different from the <code>char</code> type the <code>std::byte</code> type intends to merely represent an 8-bit value. In order to use <code>std::byte</code> the <code><cstddef></code> header file must be included.</p>
|
|
<p>The byte is defined as a strongly typed enum, simply embedding an <code>unsigned char</code>:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">enum</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">byte</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">char</span>
|
|
</span></span><span style="display:flex;"><span>{};
|
|
</span></span></code></pre></div><p>As a <code>byte</code> is an enum without predefined enum values plain assignments can only be used between <code>byte</code> values. <code>Byte</code> variables can be initialized using curly brackets around an existing <code>byte</code> or around fixed values of at most 8 bits (see #1 in the following example). If the specified value doesn’t fit in 8 bits (#2) or if the specified value is neither a <code>byte</code> nor an <code>unsigned char</code> type variable (#3) the compiler reports an error.</p>
|
|
<p>Assignments or assignment-like initializations using rvalues which are bytes initialized using parentheses with values not fitting in 8 bits are accepted (#4, #5). In these cases, the specified values are truncated to their lowest 8 bits. Here are the illustrations:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>byte value{ <span style="color:#ae81ff">0x23</span> }; <span style="color:#75715e">// #1 (see the text above)
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// byte error{ 0x123 }; // #2
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">char</span> ch <span style="color:#f92672">=</span> <span style="color:#ae81ff">0xfb</span>;
|
|
</span></span><span style="display:flex;"><span><span style="color:#75715e">// byte error{ ch }; // #3
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span>byte b1 <span style="color:#f92672">=</span> byte( ch ); <span style="color:#75715e">// #4
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>value <span style="color:#f92672">=</span> byte( <span style="color:#ae81ff">0x123</span> ); <span style="color:#75715e">// #5
|
|
</span></span></span></code></pre></div><p>The byte type supports all bit-wise operations, but the right-hand operand of the bit-wise operator must also be a byte. E.g.,</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>value <span style="color:#f92672">&=</span> byte(<span style="color:#ae81ff">0xf0</span>);
|
|
</span></span></code></pre></div><p>Byte type values can also be ordered and compared for (in)equality.</p>
|
|
<p>Unfortunately, no other operations are supported. E.g., bytes cannot be added and cannot be inserted into or extracted from streams, which somehow renders the <code>std::byte</code> less useful than ordinary types (like <code>unsigned int</code>, <code>uint16_t</code>). When needed such operations can be supported using casts (covered in section
|
|
<a href="/cpp/docs/A-First-Impression/#35-a-new-syntax-for-casts">3.5</a>), but it’s considered good practice to avoid casts whenever possible. However, C++ allows us to define a byte-type that does behave like an ordinary numeric type, including and extracting its values into and from streams. In section
|
|
<a href="/cpp/">11.4</a> such a type is developed.</p>
|
|
<h3 id="347-digit-separators">
|
|
3.4.7: Digit separators
|
|
<a class="anchor" href="#347-digit-separators">#</a>
|
|
</h3>
|
|
<p>To improve the readability of large numbers digit separators for integer and floating point literals can be used. The digit separator is a single quote which may be inserted between digits of such literals to enhance human readability. Multiple digit separators may be used, but only one separator can be inserted between successive digits. E.g.,</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>1<span style="color:#e6db74">'000'</span><span style="color:#ae81ff">000</span>
|
|
</span></span><span style="display:flex;"><span>3.141<span style="color:#e6db74">'592'</span>653<span style="color:#e6db74">'589'</span>793<span style="color:#e6db74">'238'</span><span style="color:#ae81ff">5</span>
|
|
</span></span><span style="display:flex;"><span><span style="color:#e6db74">''</span><span style="color:#ae81ff">123</span> // won<span style="color:#e6db74">'t compile
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">1''23 // won'</span>t compile either
|
|
</span></span></code></pre></div><h2 id="35-a-new-syntax-for-casts">
|
|
3.5: A new syntax for casts
|
|
<a class="anchor" href="#35-a-new-syntax-for-casts">#</a>
|
|
</h2>
|
|
<p>Traditionally, C offers the following cast syntax:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>(<span style="color:#66d9ef">typename</span>)expression
|
|
</span></span></code></pre></div><p>here typename is the name of a valid type, and expression is an expression.</p>
|
|
<p>C style casts are now deprecated. C++ programs should merely use the new style C++ casts as they offer the compiler facilities to verify the sensibility of the cast. Facilities which are not offered by the classic C-style cast.</p>
|
|
<p>A cast should not be confused with the often used constructor notation:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">typename</span>(expression)
|
|
</span></span></code></pre></div><p>the constructor notation is not a cast, but a request to the compiler to construct an (anonymous) variable of type typename from expression.</p>
|
|
<p>If casts are really necessary one of several new-style casts should be used. These new-style casts are introduced in the upcoming sections.</p>
|
|
<h3 id="351-the-static_cast-operator">
|
|
3.5.1: The <strong>static_cast</strong> operator
|
|
<a class="anchor" href="#351-the-static_cast-operator">#</a>
|
|
</h3>
|
|
<p>The <code>static_cast<type>(expression)</code> is used to convert conceptually comparable or related types to each other. Here as well as in other C++ style casts type is the type to which the type of expression should be cast.</p>
|
|
<p>Here are some examples of situations where the static_cast can (or should) be used:</p>
|
|
<ul>
|
|
<li>
|
|
<p>When converting an int to a double.</p>
|
|
<p>This happens, for example when the quotient of two int values must be computed without losing the fraction part of the division. The sqrt function called in the following fragment returns 2:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> x <span style="color:#f92672">=</span> <span style="color:#ae81ff">19</span>;
|
|
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> y <span style="color:#f92672">=</span> <span style="color:#ae81ff">4</span>;
|
|
</span></span><span style="display:flex;"><span>sqrt(x <span style="color:#f92672">/</span> y);
|
|
</span></span></code></pre></div></li>
|
|
<li>
|
|
<p>whereas it returns 2.179 when a <code>static_cast</code> is used, as in:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>sqrt(<span style="color:#66d9ef">static_cast</span><span style="color:#f92672"><</span><span style="color:#66d9ef">double</span><span style="color:#f92672">></span>(x) <span style="color:#f92672">/</span> y);
|
|
</span></span></code></pre></div></li>
|
|
<li>
|
|
<p>The important point to notice here is that a <code>static_cast</code> is allowed to change the representation of its expression into the representation that’s used by the destination type.</p>
|
|
</li>
|
|
<li>
|
|
<p>Also note that the division is put outside of the cast expression. If the division is performed within the cast’s expression (as in <code>static_cast<double>(x / y)</code>) an integer division has already been performed before the cast has had a chance to convert the type of an operand to double.</p>
|
|
</li>
|
|
<li>
|
|
<p>When converting enum values to int values (in any direction).</p>
|
|
<p>Here the two types use identical representations, but different semantics. Assigning an ordinary enum value to an int doesn’t require a cast, but when the enum is a strongly typed enum a cast is required. Conversely, a static_cast is required when assigning an int value to a variable of some enum type. Here is an example:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">enum</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">Enum</span>
|
|
</span></span><span style="display:flex;"><span>{
|
|
</span></span><span style="display:flex;"><span> VALUE
|
|
</span></span><span style="display:flex;"><span>};
|
|
</span></span><span style="display:flex;"><span>
|
|
</span></span><span style="display:flex;"><span>cout <span style="color:#f92672"><<</span> <span style="color:#66d9ef">static_cast</span><span style="color:#f92672"><</span><span style="color:#66d9ef">int</span><span style="color:#f92672">></span>(Enum<span style="color:#f92672">::</span>VALUE); <span style="color:#75715e">// show the numeric value
|
|
</span></span></span></code></pre></div></li>
|
|
<li>
|
|
<p>When converting related pointers to each other.</p>
|
|
<p>The <code>static_cast</code> is used in the context of class inheritance (cf. chapter
|
|
<a href="/cpp/">13</a>) to convert a pointer to a so-called <code>derived class</code> to a pointer to its base class. It cannot be used for casting unrelated types to each other (e.g., a <code>static_cast</code> cannot be used to cast a pointer to a short to a pointer to an int).</p>
|
|
<p>A <code>void *</code> is a generic pointer. It is frequently used by functions in the C library (e.g., <code>memcpy(3)</code>). Since it is the generic pointer it is related to any other pointer, and a <code>static_cast</code> should be used to convert a <code>void *</code> to an intended destination pointer. This is a somewhat awkward left-over from C, which should probably only be used in that context. Here is an example:</p>
|
|
<p>The <code>qsort</code> function from the C library expects a pointer to a (comparison) function having two <code>void const *</code> parameters. In fact, these parameters point to data elements of the array to be sorted, and so the comparison function must cast the <code>void const *</code> parameters to pointers to the elements of the array to be sorted. So, if the array is an int array[] and the compare function’s parameters are <code>void const *p1</code> and <code>void const *p2</code> then the compare function obtains the address of the int pointed to by <code>p1</code> by using:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">static_cast</span><span style="color:#f92672"><</span><span style="color:#66d9ef">int</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*></span>(p1);
|
|
</span></span></code></pre></div></li>
|
|
<li>
|
|
<p>When undoing or introducing the signed-modifier of an int-typed variable (remember that a <code>static_cast</code> is allowed to change the expression’s representation!).</p>
|
|
<p>Here is an example: the C function tolower requires an int representing the value of an unsigned char. But char by default is a signed type. To call tolower using an available char ch we should use:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>tolower(<span style="color:#66d9ef">static_cast</span><span style="color:#f92672"><</span><span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">char</span><span style="color:#f92672">></span>(ch))
|
|
</span></span></code></pre></div></li>
|
|
</ul>
|
|
<h3 id="352-the-const_cast-operator">
|
|
3.5.2: The <strong>const_cast</strong> operator
|
|
<a class="anchor" href="#352-the-const_cast-operator">#</a>
|
|
</h3>
|
|
<p>The <code>const</code> keyword has been given a special place in casting. Normally anything <code>const</code> is <code>const</code> for a good reason. Nonetheless situations may be encountered where the <code>const</code> can be ignored. For these special situations the <code>const_cast</code> should be used. Its syntax is:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">const_cast</span><span style="color:#f92672"><</span>type<span style="color:#f92672">></span>(expression)
|
|
</span></span></code></pre></div><p>A <code>const_cast<type>(expression)</code> expression is used to undo the const attribute of a (pointer) type.</p>
|
|
<p>The need for a <code>const_cast</code> may occur in combination with functions from the standard C library which traditionally weren’t always as const-aware as they should. A function <code>strfun(char *s)</code> might be available, performing some operation on its<code>char *s</code> parameter without actually modifying the characters pointed to by s. Passing <code>char const hello[] = "hello"</code>; to <code>strfun</code> produces the warning</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>passing <span style="color:#e6db74">`</span>const char *<span style="color:#e6db74">' as argument 1 of `fun(char *)'</span> discards const
|
|
</span></span></code></pre></div><p>A <code>const_cast</code> is the appropriate way to prevent the warning:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>strfun(<span style="color:#66d9ef">const_cast</span><span style="color:#f92672"><</span><span style="color:#66d9ef">char</span> <span style="color:#f92672">*></span>(hello));
|
|
</span></span></code></pre></div><h3 id="353-the-reinterpret_cast-operator">
|
|
3.5.3: The <strong>reinterpret_cast</strong> operator
|
|
<a class="anchor" href="#353-the-reinterpret_cast-operator">#</a>
|
|
</h3>
|
|
<p>The third new-style cast is used to change the interpretation of information: the <code>reinterpret_cast</code>. It is somewhat reminiscent of the static_cast, but <code>reinterpret_cast</code> should only be used when it is known that the information as defined in fact is or can be interpreted as something completely different. Its syntax is:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">reinterpret_cast</span><span style="color:#f92672"><</span>pointer type<span style="color:#f92672">></span>(pointer expression)
|
|
</span></span></code></pre></div><p>Think of the <code>reinterpret_cast</code> as a cast offering a poor-man’s union: the same memory location may be interpreted in completely different ways.</p>
|
|
<p>The <code>reinterpret_cast</code> is used, for example, in combination with the <code>write</code> function that is available for streams. In C++ streams are the preferred interface to, e.g., disk-files. The standard streams like <code>std::cin</code> and <code>std::cout</code> also are stream objects.</p>
|
|
<p>Streams intended for writing (output streams like <code>cout</code>) offer write members having the prototype</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>write(<span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*</span>buffer, <span style="color:#66d9ef">int</span> length)
|
|
</span></span></code></pre></div><p>To write the value stored within a double variable to a stream in its un-interpreted binary form the stream’s write member is used. However, as a <code>double *</code> and a <code>char *</code> point to variables using different and unrelated representations, a <code>static_cast</code> cannot be used. In this case a <code>reinterpret_cast</code> is required. To write the raw bytes of a variable double value to <code>cout</code> we use:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>cout.write(<span style="color:#66d9ef">reinterpret_cast</span><span style="color:#f92672"><</span><span style="color:#66d9ef">char</span> <span style="color:#66d9ef">const</span> <span style="color:#f92672">*></span>(<span style="color:#f92672">&</span>value), <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">double</span>));
|
|
</span></span></code></pre></div><p>All casts are potentially dangerous, but the <code>reinterpret_cast</code> is the most dangerous of them all. Effectively we tell the compiler: back off, we know what we’re doing, so stop fuzzing. All bets are off, and we’d better do know what we’re doing in situations like these. As a case in point consider the following code:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> value <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x12345678</span>; <span style="color:#75715e">// assume a 32-bits int
|
|
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
|
|
</span></span><span style="display:flex;"><span>cout <span style="color:#f92672"><<</span> <span style="color:#e6db74">"Value's first byte has value: "</span> <span style="color:#f92672"><<</span> hex <span style="color:#f92672"><<</span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">static_cast</span><span style="color:#f92672"><</span><span style="color:#66d9ef">int</span><span style="color:#f92672">></span>(
|
|
</span></span><span style="display:flex;"><span> <span style="color:#f92672">*</span><span style="color:#66d9ef">reinterpret_cast</span><span style="color:#f92672"><</span><span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">char</span> <span style="color:#f92672">*></span>(<span style="color:#f92672">&</span>value)
|
|
</span></span><span style="display:flex;"><span> );
|
|
</span></span></code></pre></div><p>The above code produces different results on little and big endian computers. Little endian computers show the value 78, big endian computers the value 12. Also note that the different representations used by little and big endian computers renders the previous example (<code>cout.write(...)</code>) non-portable over computers of different architectures.</p>
|
|
<p>As a rule of thumb: if circumstances arise in which casts have to be used, clearly document the reasons for their use in your code, making double sure that the cast does not eventually cause a program to misbehave. Also: avoid <code>reinterpret_casts</code> unless you have to use them.</p>
|
|
<h3 id="354-the-dynamic_cast-operator">
|
|
3.5.4: The <strong>dynamic_cast</strong> operator
|
|
<a class="anchor" href="#354-the-dynamic_cast-operator">#</a>
|
|
</h3>
|
|
<p>Finally there is a new style cast that is used in combination with polymorphism (see chapter
|
|
<a href="/cpp/">14</a>). Its syntax is:</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">dynamic_cast</span><span style="color:#f92672"><</span>type<span style="color:#f92672">></span>(expression)
|
|
</span></span></code></pre></div><p>Different from the <code>static_cast</code>, whose actions are completely determined compile-time, the <code>dynamic_cast</code>’s actions are determined run-time to convert a pointer to an object of some class (e.g., Base) to a pointer to an object of another class (e.g., Derived) which is found further down its so-called class hierarchy (this is also called downcasting).</p>
|
|
<p>At this point in the Annotations a <code>dynamic_cast</code> cannot yet be discussed extensively, but we return to this topic in section
|
|
<a href="/cpp/">14.6.1</a>.</p>
|
|
<h3 id="355-casting-shared_ptr-objects">
|
|
3.5.5: Casting <strong>shared_ptr</strong> objects
|
|
<a class="anchor" href="#355-casting-shared_ptr-objects">#</a>
|
|
</h3>
|
|
<p>This section can safely be skipped without loss of continuity.</p>
|
|
<p>In the context of the class <code>shared_ptr</code>, which is covered in section
|
|
<a href="/cpp/">18.4</a>, several more new-style casts are available. Actual coverage of these specialized casts is postponed until section
|
|
<a href="/cpp/">18.4.5</a>.</p>
|
|
<p>These specialized casts are:</p>
|
|
<ul>
|
|
<li><strong>static_pointer_cast</strong>, returning a <code>shared_ptr</code> to the <code>base-class</code> section of a <code>derived class</code> object;</li>
|
|
<li><strong>const_pointer_cast</strong>, returning a <code>shared_ptr</code> to a non-const object from a <code>shared_ptr</code> to a constant object;</li>
|
|
<li><strong>dynamic_pointer_cast</strong>, returning a <code>shared_ptr</code> to a <code>derived class</code> object from a <code>shared_ptr</code> to a base class object.</li>
|
|
</ul>
|
|
<h2 id="36-keywords-and-reserved-names-in-c">
|
|
3.6: Keywords and reserved names in C++
|
|
<a class="anchor" href="#36-keywords-and-reserved-names-in-c">#</a>
|
|
</h2>
|
|
<p>C++’s keywords are a superset of C’s keywords. Here is a list of all keywords of the language:</p>
|
|
<pre tabindex="0"><code>alignas char16_t double long reinterpret_cast true
|
|
alignof char32_t dynamic_cast module requires try
|
|
and class else mutable return typedef
|
|
and_eq co_await enum namespace short typeid
|
|
asm co_return explicit new signed typename
|
|
atomic_cancel co_yield export noexcept sizeof union
|
|
atomic_commit compl extern not static unsigned
|
|
atomic_noexcept concept false not_eq static_assert using
|
|
auto const float nullptr static_cast virtual
|
|
bitand const_cast for operator struct void
|
|
bitor constexpr friend or switch volatile
|
|
bool continue goto or_eq synchronized wchar_t
|
|
break decltype if private template while
|
|
case default import protected this xor
|
|
catch delete inline public thread_local xor_eq
|
|
char do int register throw
|
|
</code></pre><p>Notes:</p>
|
|
<ul>
|
|
<li>
|
|
<p>Since the C++17 standard the keyword <code>register</code> is no longer used, but it remains a reserved identifier. In other words, definitions like</p>
|
|
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">register</span> <span style="color:#66d9ef">int</span> index;
|
|
</span></span></code></pre></div><p>result in compilation errors. Also, <code>register</code> is no longer considered a storage class specifier (storage class specifiers are <code>extern</code>, <code>thread_local</code>, <code>mutable</code> and <code>static</code>).</p>
|
|
</li>
|
|
<li>
|
|
<p>the operator keywords: <code>and</code>, <code>and_eq</code>, <code>bitand</code>, <code>bitor</code>, <code>compl</code>, <code>not</code>, <code>not_eq</code>, <code>or</code>, <code>or_eq</code>, <code>xor</code> and <code>xor_eq</code> are symbolic alternatives for, respectively, <code>&&</code>, <code>&=</code>, <code>&</code>, <code>|</code>, <code>~</code>, <code>!</code>, <code>!=</code>, <code>||</code>, <code>|=</code>, <code>^</code> and <code>^=</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>C++ also recognizes the special identifiers final, override, transaction_safe, and transaction_safe_override. These identifiers are special in the sense that they acquire special meanings when declaring classes or polymorphic functions. Section
|
|
<a href="/cpp/">14.4</a> provides further details.</p>
|
|
</li>
|
|
</ul>
|
|
<p>Keywords can only be used for their intended purpose and cannot be used as names for other entities (e.g., variables, functions, class-names, etc.). In addition to keywords identifiers starting with an underscore and living in the global namespace (i.e., not using any explicit namespace or using the mere <code>::</code> namespace specification) or living in the <code>std</code> namespace are reserved identifiers in the sense that their use is a prerogative of the implementor.</p>
|
|
</article>
|
|
|
|
|
|
|
|
<footer class="book-footer">
|
|
|
|
<div class="flex flex-wrap justify-between">
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<script>(function(){function e(e){const t=window.getSelection(),n=document.createRange();n.selectNodeContents(e),t.removeAllRanges(),t.addRange(n)}document.querySelectorAll("pre code").forEach(t=>{t.addEventListener("click",function(){if(window.getSelection().toString())return;e(t.parentElement),navigator.clipboard&&navigator.clipboard.writeText(t.parentElement.textContent)})})})()</script>
|
|
|
|
|
|
|
|
|
|
</footer>
|
|
|
|
|
|
|
|
<div class="book-comments">
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<label for="menu-control" class="hidden book-menu-overlay"></label>
|
|
</div>
|
|
|
|
|
|
</main>
|
|
|
|
|
|
</body>
|
|
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|