]>
Commit | Line | Data |
---|---|---|
c34b1796 AL |
1 | % Box Syntax and Patterns |
2 | ||
3 | Currently the only stable way to create a `Box` is via the `Box::new` method. | |
4 | Also it is not possible in stable Rust to destructure a `Box` in a match | |
5 | pattern. The unstable `box` keyword can be used to both create and destructure | |
6 | a `Box`. An example usage would be: | |
7 | ||
62682a34 | 8 | ```rust |
c34b1796 AL |
9 | #![feature(box_syntax, box_patterns)] |
10 | ||
11 | fn main() { | |
12 | let b = Some(box 5); | |
13 | match b { | |
14 | Some(box n) if n < 0 => { | |
15 | println!("Box contains negative number {}", n); | |
16 | }, | |
17 | Some(box n) if n >= 0 => { | |
18 | println!("Box contains non-negative number {}", n); | |
19 | }, | |
20 | None => { | |
21 | println!("No box"); | |
22 | }, | |
23 | _ => unreachable!() | |
24 | } | |
25 | } | |
26 | ``` | |
27 | ||
28 | Note that these features are currently hidden behind the `box_syntax` (box | |
29 | creation) and `box_patterns` (destructuring and pattern matching) gates | |
30 | because the syntax may still change in the future. | |
31 | ||
32 | # Returning Pointers | |
33 | ||
34 | In many languages with pointers, you'd return a pointer from a function | |
35 | so as to avoid copying a large data structure. For example: | |
36 | ||
62682a34 | 37 | ```rust |
c34b1796 AL |
38 | struct BigStruct { |
39 | one: i32, | |
40 | two: i32, | |
476ff2be | 41 | // Etc. |
c34b1796 AL |
42 | one_hundred: i32, |
43 | } | |
44 | ||
45 | fn foo(x: Box<BigStruct>) -> Box<BigStruct> { | |
46 | Box::new(*x) | |
47 | } | |
48 | ||
49 | fn main() { | |
50 | let x = Box::new(BigStruct { | |
51 | one: 1, | |
52 | two: 2, | |
53 | one_hundred: 100, | |
54 | }); | |
55 | ||
56 | let y = foo(x); | |
57 | } | |
58 | ``` | |
59 | ||
60 | The idea is that by passing around a box, you're only copying a pointer, rather | |
62682a34 | 61 | than the hundred `i32`s that make up the `BigStruct`. |
c34b1796 AL |
62 | |
63 | This is an antipattern in Rust. Instead, write this: | |
64 | ||
65 | ```rust | |
66 | #![feature(box_syntax)] | |
67 | ||
68 | struct BigStruct { | |
69 | one: i32, | |
70 | two: i32, | |
476ff2be | 71 | // Etc. |
c34b1796 AL |
72 | one_hundred: i32, |
73 | } | |
74 | ||
75 | fn foo(x: Box<BigStruct>) -> BigStruct { | |
76 | *x | |
77 | } | |
78 | ||
79 | fn main() { | |
80 | let x = Box::new(BigStruct { | |
81 | one: 1, | |
82 | two: 2, | |
83 | one_hundred: 100, | |
84 | }); | |
85 | ||
86 | let y: Box<BigStruct> = box foo(x); | |
87 | } | |
88 | ``` | |
89 | ||
90 | This gives you flexibility without sacrificing performance. | |
91 | ||
92 | You may think that this gives us terrible performance: return a value and then | |
93 | immediately box it up ?! Isn't this pattern the worst of both worlds? Rust is | |
94 | smarter than that. There is no copy in this code. `main` allocates enough room | |
95 | for the `box`, passes a pointer to that memory into `foo` as `x`, and then | |
96 | `foo` writes the value straight into the `Box<T>`. | |
97 | ||
98 | This is important enough that it bears repeating: pointers are not for | |
99 | optimizing returning values from your code. Allow the caller to choose how they | |
100 | want to use your output. |