In this lesson, you will learn how to create structs that store references by using lifetime annotations to ensure your data stays valid.
The Problem with References in Structs
So far, you’ve learned how to pass references into functions. However, if you want a struct to hold a reference to some data, Rust needs to be certain that the data will live at least as long as the struct itself. If the data is destroyed while the struct is still trying to point to it, you would have a "dangling pointer"—a major security risk.
To solve this, when a struct stores a reference, you must add lifetime parameters.
Adding Lifetime Annotations
If you have a struct that holds a string slice (&str), you need to tell the compiler that the reference inside the struct is tied to a specific scope. We do this by adding a lifetime parameter, typically named 'a.
struct Book<'a> {
title: &'a str,
}
fn main() {
let name = String::from("Rust Programming");
// The struct 'book' contains a reference to 'name'.
// Because of the 'a annotation, the compiler ensures
// that 'book' cannot outlive 'name'.
let book = Book { title: &name };
println!("Reading: {}", book.title);
}
Breaking Down the Syntax
- Declaration: We add
<'a>after the struct name. This declares a generic lifetime parameter. - Field: In the struct field, we use
&'a str. This tells Rust: "This field holds a reference that lives for at least as long as the lifetime'a." - The Contract: By putting the same
'aon both the struct declaration and the field, you are creating a constraint: theBookinstance cannot exist longer than the string it refers to.
If you tried to create a Book from a string that went out of scope before the Book itself, the borrow checker would stop you immediately, preventing a memory error before it even happens. Think of the lifetime parameter as a label that ensures the "container" (the struct) never lives longer than the "content" (the referenced data).
Key Takeaway: When a struct holds a reference, you must use lifetime annotations to explicitly define the relationship between the struct's lifespan and the data it points to.