mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-01-31 11:01:46 +02:00
71ce061cc2
* Update lifetimes-data-structures.md The example is quite simple, but in it's simplicity it may raise the question why do we even need lifetimes in the structs? Isn't it obvious that the referenced value should always outlive the struct? This sentence tries to explain that more complex cases exist. * Fix typo Co-authored-by: Andrew Walbran <qwandor@google.com>
1.3 KiB
1.3 KiB
Lifetimes in Data Structures
If a data type stores borrowed data, it must be annotated with a lifetime:
#[derive(Debug)]
struct Highlight<'doc>(&'doc str);
fn erase(text: String) {
println!("Bye {text}!");
}
fn main() {
let text = String::from("The quick brown fox jumps over the lazy dog.");
let fox = Highlight(&text[4..19]);
let dog = Highlight(&text[35..43]);
// erase(text);
println!("{fox:?}");
println!("{dog:?}");
}
- In the above example, the annotation on
Highlight
enforces that the data underlying the contained&str
lives at least as long as any instance ofHighlight
that uses that data. - If
text
is consumed before the end of the lifetime offox
(ordog
), the borrow checker throws an error. - Types with borrowed data force users to hold on to the original data. This can be useful for creating lightweight views, but it generally makes them somewhat harder to use.
- When possible, make data structures own their data directly.
- Some structs with multiple references inside can have more than one lifetime annotation. This can be necessary if there is a need to describe lifetime relationships between the references themselves, in addition to the lifetime of the struct itself. Those are very advanced use cases.