diff options
| author | bors <bors@rust-lang.org> | 2014-05-27 19:31:46 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-05-27 19:31:46 -0700 |
| commit | 73dac7e4e61aa88cfc98433b61ba131b38af978d (patch) | |
| tree | 3ec3b38b9e7929169b43469e8c1a60bcf9a502d8 /src/doc/guide-pointers.md | |
| parent | 911cc9c35234ab12a4b9a6fc1cb35b52556f242d (diff) | |
| parent | 0cae84959568859f946dffb1e9d9e1d43e05ae6b (diff) | |
| download | rust-73dac7e4e61aa88cfc98433b61ba131b38af978d.tar.gz rust-73dac7e4e61aa88cfc98433b61ba131b38af978d.zip | |
auto merge of #14387 : alan-andrade/rust/remove_managed_boxes_and_gc, r=brson
My main goals were: - be clear when we talk about "references" and "pointers" - remove Managed boxes completely and the concept of GC. https://github.com/mozilla/rust/issues/13987
Diffstat (limited to 'src/doc/guide-pointers.md')
| -rw-r--r-- | src/doc/guide-pointers.md | 124 |
1 files changed, 21 insertions, 103 deletions
diff --git a/src/doc/guide-pointers.md b/src/doc/guide-pointers.md index 948d033e06c..248142851b7 100644 --- a/src/doc/guide-pointers.md +++ b/src/doc/guide-pointers.md @@ -5,7 +5,7 @@ are also one of the more confusing topics for newcomers to Rust. They can also be confusing for people coming from other languages that support pointers, such as C++. This guide will help you understand this important topic. -# You don't actually need pointers +# You don't actually need pointers, use references I have good news for you: you probably don't need to care about pointers, especially as you're getting started. Think of it this way: Rust is a language @@ -75,20 +75,22 @@ pointer that satisfies that use-case: 1. Owned: `Box<Trait>` must be a pointer, because you don't know the size of the object, so indirection is mandatory. + 2. Owned: You need a recursive data structure. These can be infinite sized, so indirection is mandatory. + 3. Owned: A very, very, very rare situation in which you have a *huge* chunk of data that you wish to pass to many methods. Passing a pointer will make this more efficient. If you're coming from another language where this technique is common, such as C++, please read "A note..." below. -4. Managed: Having only a single owner to a piece of data would be inconvenient -or impossible. This is only often useful when a program is very large or very -complicated. Using a managed pointer will activate Rust's garbage collection -mechanism. -5. Reference: You're writing a function, and you need a pointer, but you don't + +4. Reference: You're writing a function, and you need a pointer, but you don't care about its ownership. If you make the argument a reference, callers can send in whatever kind they want. +5. Shared: You need to share data among tasks. You can achieve that via the +`Rc` and `Arc` types. + Five exceptions. That's it. Otherwise, you shouldn't need them. Be sceptical of pointers in Rust: use them for a deliberate purpose, not just to make the compiler happy. @@ -165,6 +167,7 @@ approximation of owned pointers follows: 1. Only one owned pointer may exist to a particular place in memory. It may be borrowed from that owner, however. + 2. The Rust compiler uses static analysis to determine where the pointer is in scope, and handles allocating and de-allocating that memory. Owned pointers are not garbage collected. @@ -248,81 +251,6 @@ fn main() { Now it'll be copying a pointer-sized chunk of memory rather than the whole struct. -# Managed Pointers - -> **Note**: the `@` form of managed pointers is deprecated and behind a -> feature gate (it requires a `#![feature(managed_pointers)]` attribute on -> the crate root). There are replacements, currently -> there is `std::rc::Rc` and `std::gc::Gc` for shared ownership via reference -> counting and garbage collection respectively. - -Managed pointers, notated by an `@`, are used when having a single owner for -some data isn't convenient or possible. This generally happens when your -program is very large and complicated. - -For example, let's say you're using an owned pointer, and you want to do this: - -~~~rust{.ignore} -struct Point { - x: int, - y: int, -} - -fn main() { - let a = box Point { x: 10, y: 20 }; - let b = a; - println!("{}", b.x); - println!("{}", a.x); -} -~~~ - -You'll get this error: - -~~~ {.notrust} -test.rs:10:20: 10:21 error: use of moved value: `a` -test.rs:10 println!("{}", a.x); - ^ -note: in expansion of format_args! -<std-macros>:158:27: 158:81 note: expansion site -<std-macros>:157:5: 159:6 note: in expansion of println! -test.rs:10:5: 10:25 note: expansion site -test.rs:8:9: 8:10 note: `a` moved here because it has type `Box<Point>`, which is moved by default (use `ref` to override) -test.rs:8 let b = a; - ^ -~~~ - -As the message says, owned pointers only allow for one owner at a time. When you assign `a` to `b`, `a` becomes invalid. Change your code to this, however: - -~~~rust -struct Point { - x: int, - y: int, -} - -fn main() { - let a = @Point { x: 10, y: 20 }; - let b = a; - println!("{}", b.x); - println!("{}", a.x); -} -~~~ - -And it works: - -~~~ {.notrust} -10 -10 -~~~ - -So why not just use managed pointers everywhere? There are two big drawbacks to -managed pointers: - -1. They activate Rust's garbage collector. Other pointer types don't share this -drawback. -2. You cannot pass this data to another task. Shared ownership across -concurrency boundaries is the source of endless pain in other languages, so -Rust does not let you do this. - # References References are the third major kind of pointer Rust supports. They are @@ -346,7 +274,7 @@ fn compute_distance(p1: &Point, p2: &Point) -> f32 { } fn main() { - let origin = @Point { x: 0.0, y: 0.0 }; + let origin = &Point { x: 0.0, y: 0.0 }; let p1 = box Point { x: 5.0, y: 3.0 }; println!("{:?}", compute_distance(origin, p1)); @@ -354,8 +282,9 @@ fn main() { ~~~ This prints `5.83095189`. You can see that the `compute_distance` function -takes in two references, but we give it a managed and unique pointer. Of -course, if this were a real program, we wouldn't have any of these pointers, +takes in two references, a reference to a value on the stack, and a reference +to a value in a box. +Of course, if this were a real program, we wouldn't have any of these pointers, they're just there to demonstrate the concepts. So how is this hard? Well, because we're ignoring ownership, the compiler needs @@ -364,9 +293,11 @@ safety, a reference's representation at runtime is the same as that of an ordinary pointer in a C program. They introduce zero overhead. The compiler does all safety checks at compile time. -This theory is called 'region pointers,' and involve a concept called -'lifetimes'. Here's the simple explanation: would you expect this code to -compile? +This theory is called 'region pointers' and you can read more about it +[here](http://www.cs.umd.edu/projects/cyclone/papers/cyclone-regions.pdf). +Region pointers evolved into what we know today as 'lifetimes'. + +Here's the simple explanation: would you expect this code to compile? ~~~rust{.ignore} fn main() { @@ -461,24 +392,12 @@ fn main() { } ~~~ -This gives you flexibility, without sacrificing performance. For example, this will -also work: - -~~~rust -fn foo(x: Box<int>) -> int { - return *x; -} - -fn main() { - let x = box 5; - let y = @foo(x); -} -~~~ +This gives you flexibility, without sacrificing performance. You may think that this gives us terrible performance: return a value and then -immediately box it up?!?! Isn't that the worst of both worlds? Rust is smarter +immediately box it up ?! Isn't that the worst of both worlds? Rust is smarter than that. There is no copy in this code. `main` allocates enough room for the -`@int`, passes a pointer to that memory into `foo` as `x`, and then `foo` writes +`box int`, passes a pointer to that memory into `foo` as `x`, and then `foo` writes the value straight into that pointer. This writes the return value directly into the allocated box. @@ -486,7 +405,6 @@ This is important enough that it bears repeating: pointers are not for optimizin returning values from your code. Allow the caller to choose how they want to use your output. - # Related Resources * [Lifetimes guide](guide-lifetimes.html) |
