easy_rust/Chapter_19.html

383 lines
26 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> Copy types - 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> Updates</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"><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" class="active"><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" 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 id="copy-types"><a class="header" href="#copy-types">Copy types</a></h2>
<p>Some types in Rust are very simple. They are called <strong>copy types</strong>. These simple types are all on the stack, and the compiler knows their size. That means that they are very easy to copy, so the compiler always copies when you send it to a function. It always copies because they are so small and easy that there is no reason not to copy. So you don't need to worry about ownership for these types.</p>
<p>These simple types include: integers, floats, booleans (<code>true</code> and <code>false</code>), and <code>char</code>.</p>
<p>How do you know if a type <strong>implements</strong> copy? (implements = can use) You can check the documentation. For example, here is the documentation for char:</p>
<p><a href="https://doc.rust-lang.org/std/primitive.char.html">https://doc.rust-lang.org/std/primitive.char.html</a></p>
<p>On the left you can see <strong>Trait Implementations</strong>. You can see for example <strong>Copy</strong>, <strong>Debug</strong>, and <strong>Display</strong>. So you know that a <code>char</code>:</p>
<ul>
<li>is copied when you send it to a function (<strong>Copy</strong>)</li>
<li>can use <code>{}</code> to print (<strong>Display</strong>)</li>
<li>can use <code>{:?}</code> to print (<strong>Debug</strong>)</li>
</ul>
<pre><pre class="playground"><code class="language-rust">fn prints_number(number: i32) { // There is no -&gt; so it's not returning anything
// If number was not copy type, it would take it
// and we couldn't use it again
println!(&quot;{}&quot;, number);
}
fn main() {
let my_number = 8;
prints_number(my_number); // Prints 8. prints_number gets a copy of my_number
prints_number(my_number); // Prints 8 again.
// No problem, because my_number is copy type!
}
</code></pre></pre>
<p>But if you look at the documentation for String, it is not copy type.</p>
<p><a href="https://doc.rust-lang.org/std/string/struct.String.html">https://doc.rust-lang.org/std/string/struct.String.html</a></p>
<p>On the left in <strong>Trait Implementations</strong> you can look in alphabetical order. A, B, C... there is no <strong>Copy</strong> in C. But there is <strong>Clone</strong>. <strong>Clone</strong> is similar to <strong>Copy</strong>, but usually needs more memory. Also, you have to call it with <code>.clone()</code> - it won't clone just by itself.</p>
<p>In this example, <code>prints_country()</code> prints the country name, a <code>String</code>. We want to print it two times, but we can't:</p>
<pre><pre class="playground"><code class="language-rust">fn prints_country(country_name: String) {
println!(&quot;{}&quot;, country_name);
}
fn main() {
let country = String::from(&quot;Kiribati&quot;);
prints_country(country);
prints_country(country); // ⚠️
}
</code></pre></pre>
<p>But now we understand the message.</p>
<pre><code class="language-text">error[E0382]: use of moved value: `country`
--&gt; src\main.rs:4:20
|
2 | let country = String::from(&quot;Kiribati&quot;);
| ------- move occurs because `country` has type `std::string::String`, which does not implement the `Copy` trait
3 | prints_country(country);
| ------- value moved here
4 | prints_country(country);
| ^^^^^^^ value used here after move
</code></pre>
<p>The important part is <code>which does not implement the Copy trait</code>. But in the documentation we saw that String implements the <code>Clone</code> trait. So we can add <code>.clone()</code> to our code. This creates a clone, and we send the clone to the function. Now <code>country</code> is still alive, so we can use it.</p>
<pre><pre class="playground"><code class="language-rust">fn prints_country(country_name: String) {
println!(&quot;{}&quot;, country_name);
}
fn main() {
let country = String::from(&quot;Kiribati&quot;);
prints_country(country.clone()); // make a clone and give it to the function. Only the clone goes in, and country is still alive
prints_country(country);
}
</code></pre></pre>
<p>Of course, if the <code>String</code> is very large, <code>.clone()</code> can use a lot of memory. One <code>String</code> can be a whole book in length, and every time we call <code>.clone()</code> it will copy the book. So using <code>&amp;</code> for a reference is faster, if you can. For example, this code pushes a <code>&amp;str</code> onto a <code>String</code> and then makes a clone every time it gets used in a function:</p>
<pre><pre class="playground"><code class="language-rust">fn get_length(input: String) { // Takes ownership of a String
println!(&quot;It's {} words long.&quot;, input.split_whitespace().count()); // splits to count the number of words
}
fn main() {
let mut my_string = String::new();
for _ in 0..50 {
my_string.push_str(&quot;Here are some more words &quot;); // push the words on
get_length(my_string.clone()); // gives it a clone every time
}
}
</code></pre></pre>
<p>It prints:</p>
<pre><code class="language-text">It's 5 words long.
It's 10 words long.
...
It's 250 words long.
</code></pre>
<p>That's 50 clones. Here it is using a reference instead, which is better:</p>
<pre><pre class="playground"><code class="language-rust">fn get_length(input: &amp;String) {
println!(&quot;It's {} words long.&quot;, input.split_whitespace().count());
}
fn main() {
let mut my_string = String::new();
for _ in 0..50 {
my_string.push_str(&quot;Here are some more words &quot;);
get_length(&amp;my_string);
}
}
</code></pre></pre>
<p>Instead of 50 clones, it's zero.</p>
<h3 id="variables-without-values"><a class="header" href="#variables-without-values">Variables without values</a></h3>
<p>A variable without a value is called an &quot;uninitialized&quot; variable. Uninitialized means &quot;hasn't started yet&quot;. They are simple: just write <code>let</code> and the variable name:</p>
<pre><pre class="playground"><code class="language-rust">fn main() {
let my_variable; // ⚠️
}
</code></pre></pre>
<p>But you can't use it yet, and Rust won't compile if anything is uninitialized.</p>
<p>But sometimes they can be useful. A good example is when:</p>
<ul>
<li>You have a code block and the value for your variable is inside it, and</li>
<li>The variable needs to live outside of the code block.</li>
</ul>
<pre><pre class="playground"><code class="language-rust">fn loop_then_return(mut counter: i32) -&gt; i32 {
loop {
counter += 1;
if counter % 50 == 0 {
break;
}
}
counter
}
fn main() {
let my_number;
{
// Pretend we need to have this code block
let number = {
// Pretend there is code here to make a number
// Lots of code, and finally:
57
};
my_number = loop_then_return(number);
}
println!(&quot;{}&quot;, my_number);
}
</code></pre></pre>
<p>This prints <code>100</code>.</p>
<p>You can see that <code>my_number</code> was declared in the <code>main()</code> function, so it lives until the end. But it gets its value from inside a loop. However, that value lives as long as <code>my_number</code>, because <code>my_number</code> has the value. And if you wrote <code>let my_number = loop_then_return(number)</code> inside the block, it would just die right away.</p>
<p>It helps to imagine if you simplify the code. <code>loop_then_return(number)</code> gives the result 100, so let's delete it and write <code>100</code> instead. Also, now we don't need <code>number</code> so we will delete it too. Now it looks like this:</p>
<pre><pre class="playground"><code class="language-rust">fn main() {
let my_number;
{
my_number = 100;
}
println!(&quot;{}&quot;, my_number);
}
</code></pre></pre>
<p>So it's almost like saying <code>let my_number = { 100 };</code>.</p>
<p>Also note that <code>my_number</code> is not <code>mut</code>. We didn't give it a value until we gave it 50, so it never changed its value. In the end, the real code for <code>my_number</code> is just <code>let my_number = 100;</code>.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="Chapter_18.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_20.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_18.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_20.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>