fn main() {
let b = Box::new(5);
println!("b = {b}");
}
From the bookThis program will print b = 5; in this case, we can access the data in the box similarly to how we would if this data were on the stack.Read in context
Memorybox-memory
After let b = Box::new(5);, where is each part stored?
From the bookBoxes allow you to store data on the heap rather than the stack. What remains on the stack is the pointer to the heap data.Read in context
Memorybox-dropChoose TWO
b is a Box<i32> created in main. Which TWO things happen when b goes out of scope at the end of main?
From the bookJust like any owned value, when a box goes out of scope, as b does at the end of main, it will be deallocated. The deallocation happens both for the box (stored on the stack) and the data it points to (stored on the heap).Read in context
Coderecursive-types
What happens when you compile this code?
enum List {
Cons(i32, List),
Nil,
}
use crate::List::{Cons, Nil};
fn main() {
let list = Cons(1, Cons(2, Cons(3, Nil)));
}
From the bookThe error shows this type “has infinite size.” The reason is that we’ve defined List with a variant that is recursive: It holds another value of itself directly.Read in context
Coderecursive-types
Which change to the Cons variant makes this enum compile while keeping it a list of lists?
enum List {
Cons(i32, List),
Nil,
}
From the bookBecause a Box<T> is a pointer, Rust always knows how much space a Box<T> needs: A pointer’s size doesn’t change based on the amount of data it’s pointing to. This means we can put a Box<T> inside the Cons variant instead of another List value directly.Read in context
Coderecursive-types
List is defined as below. Which main compiles?
enum List {
Cons(i32, Box<List>),
Nil,
}
use crate::List::{Cons, Nil};
From the booklet list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));Read in context
Memorybox-memory
In this program, how many List values are stored on the heap?
enum List {
Cons(i32, Box<List>),
Nil,
}
use crate::List::{Cons, Nil};
fn main() {
let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
}
From the bookThe Box<T> will point to the next List value that will be on the heap rather than inside the Cons variant.Read in context
Memoryenum-size
How much space does Rust allocate for a value of this enum?
From the bookBecause only one variant will be used, the most space a Message value will need is the space it would take to store the largest of its variants.Read in context
Memoryrecursive-types
With enum List { Cons(i32, Box<List>), Nil }, how much space does any List value take?
From the bookWe now know that any List value will take up the size of an i32 plus the size of a box’s pointer data.Read in context
Scenariobox-use-cases
Your function takes ownership of a large amount of data and passes it on several times. Moving it is slow because the data gets copied each time. What's the MOST appropriate fix?
From the bookTo improve performance in this situation, we can store the large amount of data on the heap in a box. Then, only the small amount of pointer data is copied around on the stack, while the data it references stays in one place on the heap.Read in context
Interviewbox-use-casesChoose TWO
An interviewer asks: "When would you use Box<T>?" Which TWO answers are correct?
From the bookWhen you have a type whose size can’t be known at compile time, and you want to use a value of that type in a context that requires an exact size ... When you want to own a value, and you care only that it’s a type that implements a particular trait rather than being of a specific typeRead in context
Interviewderef-drop
An interviewer asks: "What makes Box<T> a smart pointer?"
From the bookThe Box<T> type is a smart pointer because it implements the Deref trait, which allows Box<T> values to be treated like references. When a Box<T> value goes out of scope, the heap data that the box is pointing to is cleaned up as well because of the Drop trait implementation.Read in context