]>
Commit | Line | Data |
---|---|---|
13cf67c4 XL |
1 | ## What Is Ownership? |
2 | ||
3 | Rust’s central feature is *ownership*. Although the feature is straightforward | |
4 | to explain, it has deep implications for the rest of the language. | |
5 | ||
6 | All programs have to manage the way they use a computer’s memory while running. | |
7 | Some languages have garbage collection that constantly looks for no longer used | |
8 | memory as the program runs; in other languages, the programmer must explicitly | |
9 | allocate and free the memory. Rust uses a third approach: memory is managed | |
10 | through a system of ownership with a set of rules that the compiler checks at | |
11 | compile time. None of the ownership features slow down your program while it’s | |
12 | running. | |
13 | ||
14 | Because ownership is a new concept for many programmers, it does take some time | |
15 | to get used to. The good news is that the more experienced you become with Rust | |
16 | and the rules of the ownership system, the more you’ll be able to naturally | |
17 | develop code that is safe and efficient. Keep at it! | |
18 | ||
19 | When you understand ownership, you’ll have a solid foundation for understanding | |
20 | the features that make Rust unique. In this chapter, you’ll learn ownership by | |
21 | working through some examples that focus on a very common data structure: | |
22 | strings. | |
23 | ||
24 | > ### The Stack and the Heap | |
25 | > | |
26 | > In many programming languages, you don’t have to think about the stack and | |
27 | > the heap very often. But in a systems programming language like Rust, whether | |
28 | > a value is on the stack or the heap has more of an effect on how the language | |
29 | > behaves and why you have to make certain decisions. Parts of ownership will | |
30 | > be described in relation to the stack and the heap later in this chapter, so | |
31 | > here is a brief explanation in preparation. | |
32 | > | |
74b04a01 XL |
33 | > Both the stack and the heap are parts of memory that are available to your |
34 | > code to use at runtime, but they are structured in different ways. The stack | |
35 | > stores values in the order it gets them and removes the values in the | |
36 | > opposite order. This is referred to as *last in, first out*. Think of a stack | |
37 | > of plates: when you add more plates, you put them on top of the pile, and | |
38 | > when you need a plate, you take one off the top. Adding or removing plates | |
39 | > from the middle or bottom wouldn’t work as well! Adding data is called | |
40 | > *pushing onto the stack*, and removing data is called *popping off the stack*. | |
13cf67c4 | 41 | > |
532ac7d7 XL |
42 | > All data stored on the stack must have a known, fixed size. Data with an |
43 | > unknown size at compile time or a size that might change must be stored on | |
9fa01778 | 44 | > the heap instead. The heap is less organized: when you put data on the heap, |
f9f354fc | 45 | > you request a certain amount of space. The memory allocator finds an empty |
532ac7d7 XL |
46 | > spot in the heap that is big enough, marks it as being in use, and returns a |
47 | > *pointer*, which is the address of that location. This process is called | |
48 | > *allocating on the heap* and is sometimes abbreviated as just *allocating*. | |
9fa01778 XL |
49 | > Pushing values onto the stack is not considered allocating. Because the |
50 | > pointer is a known, fixed size, you can store the pointer on the stack, but | |
532ac7d7 | 51 | > when you want the actual data, you must follow the pointer. |
13cf67c4 XL |
52 | > |
53 | > Think of being seated at a restaurant. When you enter, you state the number of | |
54 | > people in your group, and the staff finds an empty table that fits everyone | |
55 | > and leads you there. If someone in your group comes late, they can ask where | |
56 | > you’ve been seated to find you. | |
57 | > | |
532ac7d7 | 58 | > Pushing to the stack is faster than allocating on the heap because the |
f9f354fc | 59 | > allocator never has to search for a place to store new data; that |
532ac7d7 | 60 | > location is always at the top of the stack. Comparatively, allocating space |
f9f354fc | 61 | > on the heap requires more work, because the allocator must first find |
532ac7d7 XL |
62 | > a big enough space to hold the data and then perform bookkeeping to prepare |
63 | > for the next allocation. | |
9fa01778 | 64 | > |
13cf67c4 XL |
65 | > Accessing data in the heap is slower than accessing data on the stack because |
66 | > you have to follow a pointer to get there. Contemporary processors are faster | |
67 | > if they jump around less in memory. Continuing the analogy, consider a server | |
68 | > at a restaurant taking orders from many tables. It’s most efficient to get | |
69 | > all the orders at one table before moving on to the next table. Taking an | |
70 | > order from table A, then an order from table B, then one from A again, and | |
71 | > then one from B again would be a much slower process. By the same token, a | |
72 | > processor can do its job better if it works on data that’s close to other | |
73 | > data (as it is on the stack) rather than farther away (as it can be on the | |
74 | > heap). Allocating a large amount of space on the heap can also take time. | |
75 | > | |
76 | > When your code calls a function, the values passed into the function | |
77 | > (including, potentially, pointers to data on the heap) and the function’s | |
78 | > local variables get pushed onto the stack. When the function is over, those | |
79 | > values get popped off the stack. | |
80 | > | |
81 | > Keeping track of what parts of code are using what data on the heap, | |
82 | > minimizing the amount of duplicate data on the heap, and cleaning up unused | |
83 | > data on the heap so you don’t run out of space are all problems that ownership | |
84 | > addresses. Once you understand ownership, you won’t need to think about the | |
85 | > stack and the heap very often, but knowing that managing heap data is why | |
86 | > ownership exists can help explain why it works the way it does. | |
87 | ||
88 | ### Ownership Rules | |
89 | ||
90 | First, let’s take a look at the ownership rules. Keep these rules in mind as we | |
91 | work through the examples that illustrate them: | |
92 | ||
69743fb6 XL |
93 | * Each value in Rust has a variable that’s called its *owner*. |
94 | * There can only be one owner at a time. | |
95 | * When the owner goes out of scope, the value will be dropped. | |
13cf67c4 XL |
96 | |
97 | ### Variable Scope | |
98 | ||
99 | We’ve walked through an example of a Rust program already in Chapter 2. Now | |
100 | that we’re past basic syntax, we won’t include all the `fn main() {` code in | |
101 | examples, so if you’re following along, you’ll have to put the following | |
102 | examples inside a `main` function manually. As a result, our examples will be a | |
103 | bit more concise, letting us focus on the actual details rather than | |
104 | boilerplate code. | |
105 | ||
106 | As a first example of ownership, we’ll look at the *scope* of some variables. A | |
107 | scope is the range within a program for which an item is valid. Let’s say we | |
108 | have a variable that looks like this: | |
109 | ||
110 | ```rust | |
111 | let s = "hello"; | |
112 | ``` | |
113 | ||
114 | The variable `s` refers to a string literal, where the value of the string is | |
115 | hardcoded into the text of our program. The variable is valid from the point at | |
116 | which it’s declared until the end of the current *scope*. Listing 4-1 has | |
69743fb6 | 117 | comments annotating where the variable `s` is valid. |
13cf67c4 XL |
118 | |
119 | ```rust | |
74b04a01 | 120 | {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-01/src/main.rs:here}} |
13cf67c4 XL |
121 | ``` |
122 | ||
123 | <span class="caption">Listing 4-1: A variable and the scope in which it is | |
124 | valid</span> | |
125 | ||
126 | In other words, there are two important points in time here: | |
127 | ||
128 | * When `s` comes *into scope*, it is valid. | |
129 | * It remains valid until it goes *out of scope*. | |
130 | ||
131 | At this point, the relationship between scopes and when variables are valid is | |
132 | similar to that in other programming languages. Now we’ll build on top of this | |
133 | understanding by introducing the `String` type. | |
134 | ||
135 | ### The `String` Type | |
136 | ||
137 | To illustrate the rules of ownership, we need a data type that is more complex | |
9fa01778 | 138 | than the ones we covered in the [“Data Types”][data-types]<!-- ignore --> |
94222f64 XL |
139 | section of Chapter 3. The types covered previously are all a known size, can be |
140 | stored on the stack and popped off the stack when their scope is over, and can | |
141 | be quickly and trivially copied to make a new, independent instance if another | |
142 | part of code needs to use the same value in a different scope. But we want to | |
143 | look at data that is stored on the heap and explore how Rust knows when to | |
144 | clean up that data. | |
13cf67c4 XL |
145 | |
146 | We’ll use `String` as the example here and concentrate on the parts of `String` | |
e1599b0c | 147 | that relate to ownership. These aspects also apply to other complex data types, |
74b04a01 | 148 | whether they are provided by the standard library or created by you. We’ll |
e1599b0c | 149 | discuss `String` in more depth in Chapter 8. |
13cf67c4 XL |
150 | |
151 | We’ve already seen string literals, where a string value is hardcoded into our | |
152 | program. String literals are convenient, but they aren’t suitable for every | |
153 | situation in which we may want to use text. One reason is that they’re | |
154 | immutable. Another is that not every string value can be known when we write | |
155 | our code: for example, what if we want to take user input and store it? For | |
94222f64 XL |
156 | these situations, Rust has a second string type, `String`. This type manages |
157 | data allocated on the heap and as such is able to store an amount of text that | |
158 | is unknown to us at compile time. You can create a `String` from a string | |
159 | literal using the `from` function, like so: | |
13cf67c4 XL |
160 | |
161 | ```rust | |
162 | let s = String::from("hello"); | |
163 | ``` | |
164 | ||
165 | The double colon (`::`) is an operator that allows us to namespace this | |
166 | particular `from` function under the `String` type rather than using some sort | |
9fa01778 XL |
167 | of name like `string_from`. We’ll discuss this syntax more in the [“Method |
168 | Syntax”][method-syntax]<!-- ignore --> section of Chapter 5 and when we talk | |
169 | about namespacing with modules in [“Paths for Referring to an Item in the | |
170 | Module Tree”][paths-module-tree]<!-- ignore --> in Chapter 7. | |
13cf67c4 XL |
171 | |
172 | This kind of string *can* be mutated: | |
173 | ||
174 | ```rust | |
74b04a01 | 175 | {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/src/main.rs:here}} |
13cf67c4 XL |
176 | ``` |
177 | ||
178 | So, what’s the difference here? Why can `String` be mutated but literals | |
179 | cannot? The difference is how these two types deal with memory. | |
180 | ||
181 | ### Memory and Allocation | |
182 | ||
183 | In the case of a string literal, we know the contents at compile time, so the | |
184 | text is hardcoded directly into the final executable. This is why string | |
185 | literals are fast and efficient. But these properties only come from the string | |
186 | literal’s immutability. Unfortunately, we can’t put a blob of memory into the | |
187 | binary for each piece of text whose size is unknown at compile time and whose | |
188 | size might change while running the program. | |
189 | ||
190 | With the `String` type, in order to support a mutable, growable piece of text, | |
191 | we need to allocate an amount of memory on the heap, unknown at compile time, | |
192 | to hold the contents. This means: | |
193 | ||
f9f354fc XL |
194 | * The memory must be requested from the memory allocator at runtime. |
195 | * We need a way of returning this memory to the allocator when we’re | |
13cf67c4 XL |
196 | done with our `String`. |
197 | ||
198 | That first part is done by us: when we call `String::from`, its implementation | |
199 | requests the memory it needs. This is pretty much universal in programming | |
200 | languages. | |
201 | ||
202 | However, the second part is different. In languages with a *garbage collector | |
203 | (GC)*, the GC keeps track and cleans up memory that isn’t being used anymore, | |
204 | and we don’t need to think about it. Without a GC, it’s our responsibility to | |
205 | identify when memory is no longer being used and call code to explicitly return | |
206 | it, just as we did to request it. Doing this correctly has historically been a | |
207 | difficult programming problem. If we forget, we’ll waste memory. If we do it | |
208 | too early, we’ll have an invalid variable. If we do it twice, that’s a bug too. | |
209 | We need to pair exactly one `allocate` with exactly one `free`. | |
210 | ||
211 | Rust takes a different path: the memory is automatically returned once the | |
212 | variable that owns it goes out of scope. Here’s a version of our scope example | |
213 | from Listing 4-1 using a `String` instead of a string literal: | |
214 | ||
215 | ```rust | |
74b04a01 | 216 | {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-02-string-scope/src/main.rs:here}} |
13cf67c4 XL |
217 | ``` |
218 | ||
219 | There is a natural point at which we can return the memory our `String` needs | |
5869c6ff | 220 | to the allocator: when `s` goes out of scope. When a variable goes out of |
94222f64 XL |
221 | scope, Rust calls a special function for us. This function is called |
222 | [`drop`][drop]<!-- ignore -->, and it’s where the author of `String` can put | |
223 | the code to return the memory. Rust calls `drop` automatically at the closing | |
224 | curly bracket. | |
13cf67c4 XL |
225 | |
226 | > Note: In C++, this pattern of deallocating resources at the end of an item’s | |
227 | > lifetime is sometimes called *Resource Acquisition Is Initialization (RAII)*. | |
228 | > The `drop` function in Rust will be familiar to you if you’ve used RAII | |
229 | > patterns. | |
230 | ||
231 | This pattern has a profound impact on the way Rust code is written. It may seem | |
232 | simple right now, but the behavior of code can be unexpected in more | |
233 | complicated situations when we want to have multiple variables use the data | |
234 | we’ve allocated on the heap. Let’s explore some of those situations now. | |
235 | ||
236 | #### Ways Variables and Data Interact: Move | |
237 | ||
238 | Multiple variables can interact with the same data in different ways in Rust. | |
69743fb6 | 239 | Let’s look at an example using an integer in Listing 4-2. |
13cf67c4 XL |
240 | |
241 | ```rust | |
74b04a01 | 242 | {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-02/src/main.rs:here}} |
13cf67c4 XL |
243 | ``` |
244 | ||
245 | <span class="caption">Listing 4-2: Assigning the integer value of variable `x` | |
246 | to `y`</span> | |
247 | ||
248 | We can probably guess what this is doing: “bind the value `5` to `x`; then make | |
249 | a copy of the value in `x` and bind it to `y`.” We now have two variables, `x` | |
250 | and `y`, and both equal `5`. This is indeed what is happening, because integers | |
251 | are simple values with a known, fixed size, and these two `5` values are pushed | |
252 | onto the stack. | |
253 | ||
254 | Now let’s look at the `String` version: | |
255 | ||
256 | ```rust | |
74b04a01 | 257 | {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-03-string-move/src/main.rs:here}} |
13cf67c4 XL |
258 | ``` |
259 | ||
260 | This looks very similar to the previous code, so we might assume that the way | |
261 | it works would be the same: that is, the second line would make a copy of the | |
262 | value in `s1` and bind it to `s2`. But this isn’t quite what happens. | |
263 | ||
264 | Take a look at Figure 4-1 to see what is happening to `String` under the | |
265 | covers. A `String` is made up of three parts, shown on the left: a pointer to | |
266 | the memory that holds the contents of the string, a length, and a capacity. | |
267 | This group of data is stored on the stack. On the right is the memory on the | |
268 | heap that holds the contents. | |
269 | ||
270 | <img alt="String in memory" src="img/trpl04-01.svg" class="center" style="width: 50%;" /> | |
271 | ||
272 | <span class="caption">Figure 4-1: Representation in memory of a `String` | |
273 | holding the value `"hello"` bound to `s1`</span> | |
274 | ||
275 | The length is how much memory, in bytes, the contents of the `String` is | |
276 | currently using. The capacity is the total amount of memory, in bytes, that the | |
f9f354fc | 277 | `String` has received from the allocator. The difference between length |
13cf67c4 XL |
278 | and capacity matters, but not in this context, so for now, it’s fine to ignore |
279 | the capacity. | |
280 | ||
281 | When we assign `s1` to `s2`, the `String` data is copied, meaning we copy the | |
282 | pointer, the length, and the capacity that are on the stack. We do not copy the | |
283 | data on the heap that the pointer refers to. In other words, the data | |
284 | representation in memory looks like Figure 4-2. | |
285 | ||
286 | <img alt="s1 and s2 pointing to the same value" src="img/trpl04-02.svg" class="center" style="width: 50%;" /> | |
287 | ||
288 | <span class="caption">Figure 4-2: Representation in memory of the variable `s2` | |
289 | that has a copy of the pointer, length, and capacity of `s1`</span> | |
290 | ||
291 | The representation does *not* look like Figure 4-3, which is what memory would | |
292 | look like if Rust instead copied the heap data as well. If Rust did this, the | |
293 | operation `s2 = s1` could be very expensive in terms of runtime performance if | |
294 | the data on the heap were large. | |
295 | ||
296 | <img alt="s1 and s2 to two places" src="img/trpl04-03.svg" class="center" style="width: 50%;" /> | |
297 | ||
298 | <span class="caption">Figure 4-3: Another possibility for what `s2 = s1` might | |
299 | do if Rust copied the heap data as well</span> | |
300 | ||
301 | Earlier, we said that when a variable goes out of scope, Rust automatically | |
302 | calls the `drop` function and cleans up the heap memory for that variable. But | |
303 | Figure 4-2 shows both data pointers pointing to the same location. This is a | |
304 | problem: when `s2` and `s1` go out of scope, they will both try to free the | |
305 | same memory. This is known as a *double free* error and is one of the memory | |
306 | safety bugs we mentioned previously. Freeing memory twice can lead to memory | |
307 | corruption, which can potentially lead to security vulnerabilities. | |
308 | ||
309 | To ensure memory safety, there’s one more detail to what happens in this | |
94222f64 XL |
310 | situation in Rust. After `let s2 = s1`, Rust considers `s1` to no longer be |
311 | valid. Therefore, Rust doesn’t need to free anything when `s1` goes out of | |
312 | scope. Check out what happens when you try to use `s1` after `s2` is created; | |
313 | it won’t work: | |
13cf67c4 XL |
314 | |
315 | ```rust,ignore,does_not_compile | |
74b04a01 | 316 | {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/src/main.rs:here}} |
13cf67c4 XL |
317 | ``` |
318 | ||
319 | You’ll get an error like this because Rust prevents you from using the | |
320 | invalidated reference: | |
321 | ||
f035d41b | 322 | ```console |
74b04a01 | 323 | {{#include ../listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt}} |
13cf67c4 XL |
324 | ``` |
325 | ||
326 | If you’ve heard the terms *shallow copy* and *deep copy* while working with | |
327 | other languages, the concept of copying the pointer, length, and capacity | |
328 | without copying the data probably sounds like making a shallow copy. But | |
329 | because Rust also invalidates the first variable, instead of being called a | |
69743fb6 | 330 | shallow copy, it’s known as a *move*. In this example, we would say that |
13cf67c4 XL |
331 | `s1` was *moved* into `s2`. So what actually happens is shown in Figure 4-4. |
332 | ||
333 | <img alt="s1 moved to s2" src="img/trpl04-04.svg" class="center" style="width: 50%;" /> | |
334 | ||
335 | <span class="caption">Figure 4-4: Representation in memory after `s1` has been | |
336 | invalidated</span> | |
337 | ||
338 | That solves our problem! With only `s2` valid, when it goes out of scope, it | |
339 | alone will free the memory, and we’re done. | |
340 | ||
341 | In addition, there’s a design choice that’s implied by this: Rust will never | |
342 | automatically create “deep” copies of your data. Therefore, any *automatic* | |
343 | copying can be assumed to be inexpensive in terms of runtime performance. | |
344 | ||
345 | #### Ways Variables and Data Interact: Clone | |
346 | ||
347 | If we *do* want to deeply copy the heap data of the `String`, not just the | |
348 | stack data, we can use a common method called `clone`. We’ll discuss method | |
349 | syntax in Chapter 5, but because methods are a common feature in many | |
350 | programming languages, you’ve probably seen them before. | |
351 | ||
352 | Here’s an example of the `clone` method in action: | |
353 | ||
354 | ```rust | |
74b04a01 | 355 | {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-05-clone/src/main.rs:here}} |
13cf67c4 XL |
356 | ``` |
357 | ||
358 | This works just fine and explicitly produces the behavior shown in Figure 4-3, | |
359 | where the heap data *does* get copied. | |
360 | ||
361 | When you see a call to `clone`, you know that some arbitrary code is being | |
362 | executed and that code may be expensive. It’s a visual indicator that something | |
363 | different is going on. | |
364 | ||
365 | #### Stack-Only Data: Copy | |
366 | ||
fc512014 | 367 | There’s another wrinkle we haven’t talked about yet. This code using integers – |
3dfed10e | 368 | part of which was shown in Listing 4-2 – works and is valid: |
13cf67c4 XL |
369 | |
370 | ```rust | |
74b04a01 | 371 | {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-06-copy/src/main.rs:here}} |
13cf67c4 XL |
372 | ``` |
373 | ||
374 | But this code seems to contradict what we just learned: we don’t have a call to | |
375 | `clone`, but `x` is still valid and wasn’t moved into `y`. | |
376 | ||
377 | The reason is that types such as integers that have a known size at compile | |
378 | time are stored entirely on the stack, so copies of the actual values are quick | |
379 | to make. That means there’s no reason we would want to prevent `x` from being | |
380 | valid after we create the variable `y`. In other words, there’s no difference | |
381 | between deep and shallow copying here, so calling `clone` wouldn’t do anything | |
382 | different from the usual shallow copying and we can leave it out. | |
383 | ||
384 | Rust has a special annotation called the `Copy` trait that we can place on | |
385 | types like integers that are stored on the stack (we’ll talk more about traits | |
fc512014 XL |
386 | in Chapter 10). If a type implements the `Copy` trait, an older variable is |
387 | still usable after assignment. Rust won’t let us annotate a type with the | |
388 | `Copy` trait if the type, or any of its parts, has implemented the `Drop` | |
389 | trait. If the type needs something special to happen when the value goes out of | |
390 | scope and we add the `Copy` annotation to that type, we’ll get a compile-time | |
391 | error. To learn about how to add the `Copy` annotation to your type to | |
392 | implement the trait, see [“Derivable Traits”][derivable-traits]<!-- ignore --> | |
393 | in Appendix C. | |
394 | ||
395 | So what types implement the `Copy` trait? You can check the documentation for | |
396 | the given type to be sure, but as a general rule, any group of simple scalar | |
397 | values can implement `Copy`, and nothing that requires allocation or is some | |
398 | form of resource can implement `Copy`. Here are some of the types that | |
399 | implement `Copy`: | |
13cf67c4 XL |
400 | |
401 | * All the integer types, such as `u32`. | |
402 | * The Boolean type, `bool`, with values `true` and `false`. | |
403 | * All the floating point types, such as `f64`. | |
404 | * The character type, `char`. | |
fc512014 XL |
405 | * Tuples, if they only contain types that also implement `Copy`. For example, |
406 | `(i32, i32)` implements `Copy`, but `(i32, String)` does not. | |
13cf67c4 XL |
407 | |
408 | ### Ownership and Functions | |
409 | ||
410 | The semantics for passing a value to a function are similar to those for | |
411 | assigning a value to a variable. Passing a variable to a function will move or | |
412 | copy, just as assignment does. Listing 4-3 has an example with some annotations | |
69743fb6 | 413 | showing where variables go into and out of scope. |
13cf67c4 XL |
414 | |
415 | <span class="filename">Filename: src/main.rs</span> | |
416 | ||
417 | ```rust | |
74b04a01 | 418 | {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-03/src/main.rs}} |
13cf67c4 XL |
419 | ``` |
420 | ||
421 | <span class="caption">Listing 4-3: Functions with ownership and scope | |
422 | annotated</span> | |
423 | ||
424 | If we tried to use `s` after the call to `takes_ownership`, Rust would throw a | |
69743fb6 | 425 | compile-time error. These static checks protect us from mistakes. Try adding |
13cf67c4 XL |
426 | code to `main` that uses `s` and `x` to see where you can use them and where |
427 | the ownership rules prevent you from doing so. | |
428 | ||
429 | ### Return Values and Scope | |
430 | ||
431 | Returning values can also transfer ownership. Listing 4-4 is an example with | |
69743fb6 | 432 | similar annotations to those in Listing 4-3. |
13cf67c4 XL |
433 | |
434 | <span class="filename">Filename: src/main.rs</span> | |
435 | ||
436 | ```rust | |
74b04a01 | 437 | {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-04/src/main.rs}} |
13cf67c4 XL |
438 | ``` |
439 | ||
440 | <span class="caption">Listing 4-4: Transferring ownership of return | |
441 | values</span> | |
442 | ||
443 | The ownership of a variable follows the same pattern every time: assigning a | |
444 | value to another variable moves it. When a variable that includes data on the | |
445 | heap goes out of scope, the value will be cleaned up by `drop` unless the data | |
446 | has been moved to be owned by another variable. | |
447 | ||
448 | Taking ownership and then returning ownership with every function is a bit | |
449 | tedious. What if we want to let a function use a value but not take ownership? | |
450 | It’s quite annoying that anything we pass in also needs to be passed back if we | |
451 | want to use it again, in addition to any data resulting from the body of the | |
452 | function that we might want to return as well. | |
453 | ||
69743fb6 | 454 | It’s possible to return multiple values using a tuple, as shown in Listing 4-5. |
13cf67c4 XL |
455 | |
456 | <span class="filename">Filename: src/main.rs</span> | |
457 | ||
458 | ```rust | |
74b04a01 | 459 | {{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-05/src/main.rs}} |
13cf67c4 XL |
460 | ``` |
461 | ||
462 | <span class="caption">Listing 4-5: Returning ownership of parameters</span> | |
463 | ||
464 | But this is too much ceremony and a lot of work for a concept that should be | |
465 | common. Luckily for us, Rust has a feature for this concept, called | |
466 | *references*. | |
9fa01778 XL |
467 | |
468 | [data-types]: ch03-02-data-types.html#data-types | |
469 | [derivable-traits]: appendix-03-derivable-traits.html | |
470 | [method-syntax]: ch05-03-method-syntax.html#method-syntax | |
532ac7d7 | 471 | [paths-module-tree]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html |
94222f64 | 472 | [drop]: ../std/ops/trait.Drop.html#tymethod.drop |