|
1 | 1 | # Smart Pointers |
2 | 2 |
|
3 | | -*Pointer* is a generic programming term for something that refers to a location |
4 | | -that stores some other data. We learned about Rust’s references in Chapter 4; |
5 | | -they’re a plain sort of pointer indicated by the `&` symbol and borrow the |
6 | | -value that they point to. *Smart pointers* are data structures that act like a |
7 | | -pointer, but also have additional metadata and capabilities, such as reference |
8 | | -counting. The smart pointer pattern originated in C++. In Rust, an additional |
9 | | -difference between plain references and smart pointers is that references are a |
10 | | -kind of pointer that only borrow data; by contrast, in many cases, smart |
11 | | -pointers *own* the data that they point to. |
12 | | - |
13 | | -We’ve actually already encountered a few smart pointers in this book, even |
14 | | -though we didn’t call them that by name at the time. For example, in a certain |
15 | | -sense, `String` and `Vec<T>` from Chapter 8 are both smart pointers. They own |
16 | | -some memory and allow you to manipulate it, and have metadata (like their |
17 | | -capacity) and extra capabilities or guarantees (`String` data will always be |
18 | | -valid UTF-8). The characteristics that distinguish a smart pointer from an |
19 | | -ordinary struct are that smart pointers implement the `Deref` and `Drop` |
20 | | -traits, and in this chapter we’ll be discussing both of those traits and why |
21 | | -they’re important to smart pointers. |
| 3 | +A *pointer* is a general concept for a variable that contains an address in |
| 4 | +memory. This address refers to, or “points at”, some other data. The most |
| 5 | +common kind of pointer in Rust is a *reference*, which we learned about in |
| 6 | +Chapter 4. References are indicated by the `&` symbol and borrow the value that |
| 7 | +they point to. They don’t have any special abilities other than referring to |
| 8 | +data. They also don’t have any overhead, so they’re used the most often. |
| 9 | + |
| 10 | +*Smart pointers*, on the other hand, are data structures that act like a |
| 11 | +pointer, but they also have additional metadata and capabilities. The concept |
| 12 | +of smart pointers isn’t unique to Rust; it originated in C++ and exists in |
| 13 | +other languages as well. The different smart pointers defined in Rust’s |
| 14 | +standard library provide extra functionality beyond what references provide. |
| 15 | +One example that we’ll explore in this chapter is the *reference counting* |
| 16 | +smart pointer type, which enables you to have multiple owners of data. The |
| 17 | +reference counting smart pointer keeps track of how many owners there are, and |
| 18 | +when there aren’t any remaining, the smart pointer takes care of cleaning up |
| 19 | +the data. |
| 20 | + |
| 21 | +<!-- maybe a brief explanation what deref and drop? I'm not really sure what |
| 22 | +reference counting is here too, can you outline that in brief?--> |
| 23 | +<!-- We've added a quick explanation of reference counting here and a brief |
| 24 | +explanation of deref and drop below. /Carol --> |
| 25 | + |
| 26 | +<!--(regarding C++) if this is relevant here, can you expand? Are we saying |
| 27 | +they will be familiar to C++ people? --> |
| 28 | +<!-- We were trying to say that "smart pointer" isn't something particular to |
| 29 | +Rust; we've tried to clarify. /Carol --> |
| 30 | + |
| 31 | +In Rust, where we have the concept of ownership and borrowing, an additional |
| 32 | +difference between references and smart pointers is that references are a kind |
| 33 | +of pointer that only borrow data; by contrast, in many cases, smart pointers |
| 34 | +*own* the data that they point to. |
| 35 | + |
| 36 | +We’ve actually already encountered a few smart pointers in this book, such as |
| 37 | +`String` and `Vec<T>` from Chapter 8, though we didn’t call them smart pointers |
| 38 | +at the time. Both these types count as smart pointers because they own some |
| 39 | +memory and allow you to manipulate it. They also have metadata (such as their |
| 40 | +capacity) and extra capabilities or guarantees (such as `String` ensuring its |
| 41 | +data will always be valid UTF-8). |
| 42 | + |
| 43 | +<!-- Above: we said smart pointers don't own values earlier but in the |
| 44 | +paragraph above we're saying String and Vec own memory, is that a |
| 45 | +contradiction? --> |
| 46 | +<!-- Our original text read: "In Rust, an additional difference between plain |
| 47 | +references and smart pointers is that references are a kind of pointer that |
| 48 | +only borrow data; by contrast, in many cases, smart pointers *own* the data |
| 49 | +that they point to." You had edited this to say the opposite: "In Rust, smart |
| 50 | +pointers can only borrow data, whereas in many other languages, smart pointers |
| 51 | +*own* the data they point to." We had the "in rust" phrase not to distinguish |
| 52 | +Rust's smart pointer implementation from other languages' smart pointer |
| 53 | +implementations, but to acknowledge that the concept of borrowing and ownership |
| 54 | +doesn't apply in many languages. The distinction between references borrowing |
| 55 | +and smart pointers owning is important in the context of Rust. We've tried to |
| 56 | +clarify the sentence talking about C++ and separate it from the discussion of |
| 57 | +borrowing vs owning. So there shouldn't be a contradiction, and it should be |
| 58 | +clearer that smart pointers usually own the data they point to. /Carol --> |
| 59 | + |
| 60 | +Smart pointers are usually implemented using structs. The characteristics that |
| 61 | +distinguish a smart pointer from an ordinary struct are that smart pointers |
| 62 | +implement the `Deref` and `Drop` traits. The `Deref` trait allows an instance |
| 63 | +of the smart pointer struct to behave like a reference so that we can write |
| 64 | +code that works with either references or smart pointers. The `Drop` trait |
| 65 | +allows us to customize the code that gets run when an instance of the smart |
| 66 | +pointer goes out of scope. In this chapter, we’ll be discussing both of those |
| 67 | +traits and demonstrating why they’re important to smart pointers. |
22 | 68 |
|
23 | 69 | Given that the smart pointer pattern is a general design pattern used |
24 | 70 | frequently in Rust, this chapter won’t cover every smart pointer that exists. |
25 | | -Many libraries have their own and you may write some yourself. The ones we |
26 | | -cover here are the most common ones from the standard library: |
| 71 | +Many libraries have their own smart pointers and you can even write some |
| 72 | +yourself. We’ll just cover the most common smart pointers from the standard |
| 73 | +library: |
| 74 | + |
| 75 | +<!-- Would it make sense to hyphenate reference-counted (and its derivations) |
| 76 | +here? I think that would be more clear, but I don't want to do that if that's |
| 77 | +not the Rust convention --> |
| 78 | +<!-- The hyphenated version doesn't appear to be a general convention to me, it |
| 79 | +looks like "reference counted" is most often not hyphenated. For example: |
| 80 | +http://researcher.watson.ibm.com/researcher/files/us-bacon/Bacon01Concurrent.pdf |
| 81 | + We'd be interested to know if there's a standard that we don't know about |
| 82 | +/Carol --> |
27 | 83 |
|
28 | | -* `Box<T>`, for allocating values on the heap |
29 | | -* `Rc<T>`, a reference counted type so data can have multiple owners |
30 | | -* `RefCell<T>`, which isn’t a smart pointer itself, but manages access to the |
31 | | - smart pointers `Ref` and `RefMut` to enforce the borrowing rules at runtime |
32 | | - instead of compile time |
| 84 | +* `Box<T>` for allocating values on the heap |
| 85 | +* `Rc<T>`, a reference counted type that enables multiple ownership |
| 86 | +* `Ref<T>` and `RefMut<T>`, accessed through `RefCell<T>`, a type that enforces |
| 87 | + the borrowing rules at runtime instead of compile time |
33 | 88 |
|
34 | | -Along the way, we’ll also cover: |
| 89 | +<!-- Should we add Ref and RefMut to this list, too? --> |
| 90 | +<!-- They were already sort of in the list; we've flipped the order to make it |
| 91 | +clearer /Carol--> |
35 | 92 |
|
36 | | -* The *interior mutability* pattern where an immutable type exposes an API for |
37 | | - mutating an interior value, and the borrowing rules apply at runtime instead |
38 | | - of compile time |
39 | | -* Reference cycles, how they can leak memory, and how to prevent them |
| 93 | +Along the way, we’ll cover the *interior mutability* pattern where an immutable |
| 94 | +type exposes an API for mutating an interior value. We’ll also discuss |
| 95 | +*reference cycles*, how they can leak memory, and how to prevent them. |
40 | 96 |
|
41 | 97 | Let’s dive in! |
0 commit comments