easy_rust/Chapter_17.html

322 lines
25 KiB
HTML
Raw Normal View History

<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title> Mutable references - Easy Rust</title>
<!-- Custom HTML head -->
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="favicon.svg">
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body>
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="Chapter_0.html"><strong aria-hidden="true">1.</strong> Update</a></li><li class="chapter-item expanded "><a href="Chapter_1.html"><strong aria-hidden="true">2.</strong> Introduction</a></li><li class="chapter-item expanded "><a href="Chapter_2.html"><strong aria-hidden="true">3.</strong> Who am I?</a></li><li class="chapter-item expanded "><a href="Chapter_3.html"><strong aria-hidden="true">4.</strong> Writing Rust in Easy English</a></li><li class="chapter-item expanded "><a href="Chapter_4.html"><strong aria-hidden="true">5.</strong> Rust Playground</a></li><li class="chapter-item expanded "><a href="Chapter_5.html"><strong aria-hidden="true">6.</strong> 🚧 and ⚠️</a></li><li class="chapter-item expanded "><a href="Chapter_6.html"><strong aria-hidden="true">7.</strong> Comments</a></li><li class="chapter-item expanded "><a href="Chapter_7.html"><strong aria-hidden="true">8.</strong> Types</a></li><li class="chapter-item expanded "><a href="Chapter_8.html"><strong aria-hidden="true">9.</strong> Type inference</a></li><li class="chapter-item expanded "><a href="Chapter_9.html"><strong aria-hidden="true">10.</strong> Printing 'hello, world!'</a></li><li class="chapter-item expanded "><a href="Chapter_10.html"><strong aria-hidden="true">11.</strong> Display and debug</a></li><li class="chapter-item expanded "><a href="Chapter_11.html"><strong aria-hidden="true">12.</strong> Mutability (changing)</a></li><li class="chapter-item expanded "><a href="Chapter_12.html"><strong aria-hidden="true">13.</strong> The stack, the heap, and pointers</a></li><li class="chapter-item expanded "><a href="Chapter_13.html"><strong aria-hidden="true">14.</strong> More about printing</a></li><li class="chapter-item expanded "><a href="Chapter_14.html"><strong aria-hidden="true">15.</strong> Strings</a></li><li class="chapter-item expanded "><a href="Chapter_15.html"><strong aria-hidden="true">16.</strong> const and static</a></li><li class="chapter-item expanded "><a href="Chapter_16.html"><strong aria-hidden="true">17.</strong> More on references</a></li><li class="chapter-item expanded "><a href="Chapter_17.html" class="active"><strong aria-hidden="true">18.</strong> Mutable references</a></li><li class="chapter-item expanded "><a href="Chapter_18.html"><strong aria-hidden="true">19.</strong> Giving references to functions</a></li><li class="chapter-item expanded "><a href="Chapter_19.html"><strong aria-hidden="true">20.</strong> Copy types</a></li><li class="chapter-item expanded "><a href="Chapter_20.html"><strong aria-hidden="true">21.</strong> Collection types</a></li><li class="chapter-item expanded "><a href="Chapter_21.html"><strong aria-hidden="true">22.</strong> Vectors</a></li><li class="chapter-item expanded "><a href="Chapter_22.html"><strong aria-hidden="true">23.</strong> Tuples</a></li><li class="chapter-item expanded "><a href="Chapter_23.html"><strong aria-hidden="true">24.</strong> Control flow</a></li><li class="chapter-item expanded "><a href="Chapter_24.html"><strong aria-hidden="true">25.</strong> Structs</a></li><li class="chapter-item expanded "><a href="Chapter_25.html"><strong aria-hidden="true">26.</strong> Enums</a></li><li class="chapter-item expanded "><a href="Chapter_26.html"><strong aria-hidden="true">27.</strong> Loops</a></li><li class="chapter-item expanded "><a href="Chapter_27.html"><strong aria-hidden="true">28.</strong> Implementing structs and enums</a></li><li class="chapter-item expanded "><a href="Chapter_28.html"><strong aria-hidden="true">29.</strong> Destructuring</a></li><li class="chapter-item expanded "><a href="Chapter_29.html"><strong aria-hidden="true">30.</strong> References and the dot operator</a></li><li class="chapter-item expanded "><a href="Chapter_30.html"><strong aria-hidden="true">31.</strong> Generics</a></li><li class="chapter-item expanded "><a href="Chapter_31.html"><strong aria-hidden="true">32.</strong> Option and Result</a></li><li class="chapter-item expanded "><a href="Chapter_32.html">
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky bordered">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">Easy Rust</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h2><a class="header" href="#mutable-references" id="mutable-references">Mutable references</a></h2>
<p>If you want to use a reference to change data, you can use a mutable reference. For a mutable reference, you write <code>&amp;mut</code> instead of <code>&amp;</code>.</p>
<pre><pre class="playground"><code class="language-rust">fn main() {
let mut my_number = 8; // don't forget to write mut here!
let num_ref = &amp;mut my_number;
}
</code></pre></pre>
<p>So what are the two types? <code>my_number</code> is an <code>i32</code>, and <code>num_ref</code> is <code>&amp;mut i32</code> (we say a &quot;mutable reference to an <code>i32</code>&quot;).</p>
<p>So let's use it to add 10 to my_number. But you can't write <code>num_ref += 10</code>, because <code>num_ref</code> is not the <code>i32</code> value, it is a <code>&amp;i32</code>. The value is actually inside the <code>i32</code>. To reach the place where the value is, we use <code>*</code>. <code>*</code> means &quot;I don't want the reference, I want the value behind the reference&quot;. In other words, one <code>*</code> is the opposite of <code>&amp;</code>. Also, one <code>*</code> erases one <code>&amp;</code>.</p>
<pre><pre class="playground"><code class="language-rust">fn main() {
let mut my_number = 8;
let num_ref = &amp;mut my_number;
*num_ref += 10; // Use * to change the i32 value.
println!(&quot;{}&quot;, my_number);
let second_number = 800;
let triple_reference = &amp;&amp;&amp;second_number;
println!(&quot;Second_number = triple_reference? {}&quot;, second_number == ***triple_reference);
}
</code></pre></pre>
<p>This prints:</p>
<pre><code class="language-text">18
Second_number = triple_reference? true
</code></pre>
<p>Because using <code>&amp;</code> is called &quot;referencing&quot;, using <code>*</code> is called &quot;<strong>de</strong>referencing&quot;.</p>
<p>Rust has two rules for mutable and immutable references. They are very important, but also easy to remember because they make sense.</p>
<ul>
<li><strong>Rule 1</strong>: If you have only immutable references, you can have as many as you want. 1 is fine, 3 is fine, 1000 is fine. No problem.</li>
<li><strong>Rule 2</strong>: If you have a mutable reference, you can only have one. Also, you can't have an immutable reference <strong>and</strong> a mutable reference together.</li>
</ul>
<p>This is because mutable references can change the data. You could get problems if you change the data when other references are reading it.</p>
<p>A good way to understand is to think of a Powerpoint presentation.</p>
<p>Situation one is about <strong>only one mutable reference</strong>.</p>
<p>Situation one: An employee is writing a Powerpoint presentation. He wants his manager to help him. The employee gives his login information to his manager, and asks him to help by making edits. Now the manager has a &quot;mutable reference&quot; to the employee's presentation. The manager can make any changes he wants, and give the computer back later. This is fine, because nobody else is looking at the presentation.</p>
<p>Situation two is about <strong>only immutable references</strong>.</p>
<p>Situation two: The employee is giving the presentation to 100 people. All 100 people can now see the employee's data. They all have an &quot;immutable reference&quot; to the employee's presentation. This is fine, because they can see it but nobody can change the data.</p>
<p>Situation three is <strong>the problem situation</strong>.</p>
<p>Situation three: The Employee gives his manager his login information. His manager now has a &quot;mutable reference&quot;. Then the employee went to give the presentation to 100 people, but the manager can still login. This is not fine, because the manager can log in and do anything. Maybe his manager will log into the computer and start typing an email to his mother! Now the 100 people have to watch the manager write an email to his mother instead of the presentation. That's not what they expected to see.</p>
<p>Here is an example of a mutable borrow with an immutable borrow:</p>
<pre><pre class="playground"><code class="language-rust">fn main() {
let mut number = 10;
let number_ref = &amp;number;
let number_change = &amp;mut number;
*number_change += 10;
println!(&quot;{}&quot;, number_ref); // ⚠️
}
</code></pre></pre>
<p>The compiler prints a helpful message to show us the problem.</p>
<pre><code class="language-text">error[E0502]: cannot borrow `number` as mutable because it is also borrowed as immutable
--&gt; src\main.rs:4:25
|
3 | let number_ref = &amp;number;
| ------- immutable borrow occurs here
4 | let number_change = &amp;mut number;
| ^^^^^^^^^^^ mutable borrow occurs here
5 | *number_change += 10;
6 | println!(&quot;{}&quot;, number_ref);
| ---------- immutable borrow later used here
</code></pre>
<p>However, this code will work. Why?</p>
<pre><pre class="playground"><code class="language-rust">fn main() {
let mut number = 10;
let number_change = &amp;mut number; // create a mutable reference
*number_change += 10; // use mutable reference to add 10
let number_ref = &amp;number; // create an immutable reference
println!(&quot;{}&quot;, number_ref); // print the immutable reference
}
</code></pre></pre>
<p>It prints <code>20</code> with no problem. It works because the compiler is smart enough to understand our code. It knows that we used <code>number_change</code> to change <code>number</code>, but didn't use it again. So here there is no problem. We are not using immutable and mutable references together.</p>
<p>Earlier in Rust this kind of code actually generated an error, but the compiler is smarter now. It can understand not just what we type, but how we use everything.</p>
<h3><a class="header" href="#shadowing-again" id="shadowing-again">Shadowing again</a></h3>
<p>Remember when we said that shadowing doesn't <strong>destroy</strong> a value but <strong>blocks</strong> it? Now we can use references to see this.</p>
<pre><pre class="playground"><code class="language-rust">fn main() {
let country = String::from(&quot;Austria&quot;);
let country_ref = &amp;country;
let country = 8;
println!(&quot;{}, {}&quot;, country_ref, country);
}
</code></pre></pre>
<p>Does this print <code>Austria, 8</code> or <code>8, 8</code>? It prints <code>Austria, 8</code>. First we declare a <code>String</code> called <code>country</code>. Then we create a reference <code>country_ref</code> to this string. Then we shadow country with 8, which is an <code>i32</code>. But the first <code>country</code> was not destroyed, so <code>country_ref</code> still says &quot;Austria&quot;, not &quot;8&quot;. Here is the same code with some comments to show how it works:</p>
<pre><pre class="playground"><code class="language-rust">fn main() {
let country = String::from(&quot;Austria&quot;); // Now we have a String called country
let country_ref = &amp;country; // country_ref is a reference to this data. It's not going to change
let country = 8; // Now we have a variable called country that is an i8. But it has no relation to the other one, or to country_ref
println!(&quot;{}, {}&quot;, country_ref, country); // country_ref still refers to the data of String::from(&quot;Austria&quot;) that we gave it.
}
</code></pre></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="Chapter_16.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="Chapter_18.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="Chapter_16.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="Chapter_18.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script type="text/javascript">
window.playground_copyable = true;
</script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
</body>
</html>