Consider the following Rust code snippet. What will it print when run?
fn main() {
let r;
{
let x = 5;
r = &x;
}
println!("{}", r);
}Think about the lifetime of x and the reference r.
The variable x is dropped at the end of the inner block, but r tries to borrow it outside that scope. Rust's borrow checker prevents this by causing a compile-time error, so the code does not compile.
Which feature of Rust ensures that references do not outlive the data they point to, thus preventing dangling references?
It is a compile-time check related to how long references are valid.
The borrow checker uses lifetimes to ensure references do not outlive the data they point to, preventing dangling references at compile time.
Why does this Rust code fail to compile?
fn get_str<'a>() -> &'a str { let s = String::from("hello"); &s }
Consider the lifetime of s compared to the returned reference.
The variable s is created inside the function and dropped when the function ends. Returning a reference to it causes a dangling reference, which Rust forbids.
Given this code that does not compile, which option fixes the dangling reference issue?
fn get_str<'a>() -> &'a str {
let s = String::from("hello");
&s
}Think about ownership and how to avoid returning references to local variables.
Returning the owned String transfers ownership and avoids dangling references. Returning a reference to a local variable is invalid.
Analyze the following Rust code. How many references are valid and safe to use after the block ends?
fn main() {
let r1;
{
let x = 10;
r1 = &x;
}
let x2 = 20;
let r2 = &x2;
println!("{} {}", r1, r2);
}Consider the scope and lifetime of x and x2.
The reference r1 points to x which is dropped after the inner block, so r1 is invalid outside. r2 points to x2 which is valid in the outer scope.
