Lifetimes in Structs
In this page:
struct Name<'a> {
field: &'a str,
}
impl<'a> Name<'a> {
fn method(&self) -> &str {
self.field
}
}
A Struct Holding a Reference
When a struct field is a reference, the struct itself needs a lifetime parameter, ensuring no instance of the struct can outlive the data it borrows.
Example: A Struct Holding a Reference
// Define a struct `Excerpt` to group related fields together
struct Excerpt<'a> {
text: &'a str,
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `novel`, set to `String::from("Call me Ishmael. Some years ago...")`
let novel = String::from("Call me Ishmael. Some years ago...");
// Declare an immutable variable `first_sentence`, set to `novel.split('.').next().unwrap()`
let first_sentence = novel.split('.').next().unwrap();
// Declare an immutable variable `excerpt`, set to `Excerpt { text: first_sentence }`
let excerpt = Excerpt { text: first_sentence };
// Print "{}" to the console, substituting in `excerpt.text` (with a trailing newline)
println!("{}", excerpt.text);
}
Login to try C/C++/Java/PHP code in the editor
Methods on a Struct with a Lifetime
An impl block for a struct that has a lifetime parameter must declare and repeat that lifetime, letting methods work with the borrowed field just like any other.
Example: Methods on a Struct with a Lifetime
// Define a struct `Excerpt` to group related fields together
struct Excerpt<'a> {
text: &'a str,
}
// Implement methods on `Excerpt`
impl<'a> Excerpt<'a> {
// Define the function `announce` taking `&self` and returning a String
fn announce(&self) -> String {
format!("Excerpt: {}", self.text)
}
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `source`, set to `String::from("Rust is reliable and fast")`
let source = String::from("Rust is reliable and fast");
// Declare an immutable variable `excerpt`, set to `Excerpt { text: &source[0..4] }`
let excerpt = Excerpt { text: &source[0..4] };
// Print "{}" to the console, substituting in `excerpt.announce()` (with a trailing newline)
println!("{}", excerpt.announce());
}
Login to try C/C++/Java/PHP code in the editor
Instances Cannot Outlive Their Data
The compiler guarantees that a struct instance holding a reference cannot be used after the data it references has gone out of scope, preventing dangling struct fields entirely.
Example: Instances Cannot Outlive Their Data
// Define a struct `Wrapper` to group related fields together
struct Wrapper<'a> {
value: &'a i32,
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `number`, set to `42`
let number = 42;
// Declare an immutable variable `wrapped`, set to `Wrapper { value: &number }`
let wrapped = Wrapper { value: &number };
// Print "{}" to the console, substituting in `wrapped.value` (with a trailing newline)
println!("{}", wrapped.value);
}
Login to try C/C++/Java/PHP code in the editor
Avoiding Lifetimes with Owned Data
If a struct owns its data (using String instead of &str, for example) it needs no lifetime parameter at all, trading a small allocation cost for simpler code.
Example: Avoiding Lifetimes with Owned Data
// Define a struct `OwnedExcerpt` to group related fields together
struct OwnedExcerpt {
text: String,
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `excerpt`, set to `OwnedExcerpt { text: String::from("No lifetime needed here") }`
let excerpt = OwnedExcerpt { text: String::from("No lifetime needed here") };
// Print "{}" to the console, substituting in `excerpt.text` (with a trailing newline)
println!("{}", excerpt.text);
}
Login to try C/C++/Java/PHP code in the editor
- Trying to store a reference in a struct field without declaring a lifetime parameter on the struct itself, which fails to compile.
- Assuming a struct holding a reference can outlive the data that reference points to -- the compiler enforces the opposite.
- Forgetting an
implblock for a struct with a lifetime parameter must also repeat that lifetime, e.g.impl<'a> MyStruct<'a>.
- A struct holding a reference field must declare a lifetime parameter, e.g.
struct Excerpt<'a> { text: &'a str }. - An instance of such a struct cannot outlive the data its reference field points to.
implblocks for a struct with a lifetime parameter must declare and repeat that same lifetime.- Storing owned data (like
Stringinstead of&str) avoids needing a lifetime parameter, at the cost of an extra allocation.
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: