@@ -8,12 +8,12 @@ What Is "Box<T>"
88
99- Allocates data on the heap (via :rust: `Box::new `)
1010
11- - Stores a fixed-size pointer on the stack
11+ - Stores a fixed-size pointer on the stack
1212
13- - Retains single ownership of heap data
13+ - Retains single ownership of heap data
14+
15+ - Deallocates memory automatically when object goes out of scope
1416
15- - Deallocates memory automatically when object goes out of scope
16-
1717- Defined in **prelude **
1818
1919.. code :: rust
@@ -23,27 +23,27 @@ What Is "Box<T>"
2323
2424 // Implicit dereference
2525 println!("Box value is {}", my_box);
26-
26+
2727 .. code :: output
2828
2929 Box value is 5
30-
30+
3131------------------------------------
3232Using "Box<T>" for Recursive Types
3333------------------------------------
3434
3535- Types must have a known size at compile time
3636
3737 - Recursive types don't have a known size
38-
38+
3939 .. code :: rust
4040
4141 // FAILS: How big is an infinite doll?
4242 enum Doll {
4343 Inside(Doll),
4444 Empty,
4545 }
46-
46+
4747 .. code :: error
4848 :font-size: small
4949
@@ -67,42 +67,92 @@ Using "Box<T>" for Recursive Types
6767Handling Large Data
6868---------------------
6969
70- - :rust: `Box<T> ` allows transferring ownership of data
71-
72- - Rather than copying data passed in parameters for function calls
73-
74- - Useful for large data
75-
76- .. code :: rust
77-
78- struct BigData {
79- samples: [u64; 1000000],
80- metadata: String,
70+ - :rust: `Box::new(large_value) ` can still require a large stack temporary
71+
72+ - Do not rely on compiler optimizations to avoid stack overflow
73+
74+ - Initialize the elements on the heap with :rust: `vec! `
75+
76+ - Convert the vector into an owned slice with :rust: `into_boxed_slice() `
77+
78+ .. code :: rust
79+
80+ fn create_data() -> Box<[u64]> {
81+ vec![0_u64; 1_000_000].into_boxed_slice()
82+ }
83+
84+ - Returning the box transfers ownership; the elements stay in place
85+
86+ .. note ::
87+
88+ This avoids a large stack temporary, but heap allocation can still fail
89+
90+ ----------------------------------
91+ Choosing a Heap-Allocated Buffer
92+ ----------------------------------
93+
94+ - :rust: `Vec<u64> ` already owns its heap buffer and is cheap to move
95+
96+ - Keep the vector if the buffer needs to grow or shrink
97+
98+ - :rust: `Box<[u64]> ` owns a heap-allocated slice with a fixed length
99+
100+ - The length is stored at runtime, unlike :rust: `Box<[u64; 1_000_000]> `
101+
102+ - A fixed length does not make the elements immutable
103+
104+ - Moving either container does not relocate its heap-allocated elements
105+
106+ - Moving a large inline value may still relocate its bytes
107+
108+ .. note ::
109+
110+ :rust: `into_boxed_slice() ` may reallocate to discard excess capacity, this conversion is different from moving an existing box
111+
112+ ------------------------------------
113+ Borrowing or Transferring Ownership
114+ ------------------------------------
115+
116+ - Borrow with :rust: `&[u64] ` when temporary access is enough
117+
118+ - The caller retains ownership; the buffer is not copied
119+
120+ - Move :rust: `Box<[u64]> ` when another value must own the buffer
121+
122+ - Ownership is transferred without copying the buffer
123+
124+ .. code :: rust
125+
126+ fn inspect_data(samples: &[u64]) {
127+ println!("{} samples", samples.len());
81128 }
82- let huge_chunk = Box::new(BigData {
83- samples: [0; 1000000],
84- metadata: String::from("Satellite Telemetry - Region A"),
85- });
86- // Only reference is moved to the function...
87- // ...not the whole array
88- process_data(huge_chunk);
89-
129+ struct DataProcessor {
130+ samples: Box<[u64]>,
131+ }
132+
133+ let samples = create_data();
134+ inspect_data(&samples); // Borrow; 'samples' is still usable
135+
136+ let processor = DataProcessor { samples }; // Move the box
137+ // 'samples' is no longer usable; 'processor' owns the buffer
138+ println!("{} samples", processor.samples.len());
139+
140+ .. note ::
141+
142+ Dropping :rust: `processor ` drops its boxed slice and frees the buffer, :rust: `&samples ` coerces to :rust: `&[u64] `
143+
90144---------------------
91145Resource Management
92146---------------------
93147
94- - :rust: `Box<T> ` implements :rust: `Drop ` to ensure memory safety
148+ - :rust: `Box<T> ` implements :rust: `Drop ` to ensure memory safety
95149
96150 - Invokes :rust: `Drop ` method automatically at end of scope
97-
151+
98152 - No need for manual intervention
99-
153+
100154 - Prevents memory leaks by ensuring deallocation
101-
102- - Transferring ownership is an *O(1) * operation
103-
104- - Regardless of what it points to
105-
106-
107155
108-
156+ - Transferring ownership is an *O(1) * operation
157+
158+ - Regardless of what it points to
0 commit comments