Bird
Raised Fist0
Rustprogramming~10 mins

Lifetimes in structs in Rust - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Lifetimes in structs
Define struct with lifetime
↓
Create instance with reference
↓
Use instance safely
↓
Lifetime ends when references drop
↓
Memory is safe, no dangling refs
This flow shows how a struct with a lifetime parameter holds references safely until they go out of scope.
Execution Sample
Rust
struct Holder<'a> {
    value: &'a str,
}

fn main() {
    let text = String::from("hello");
    let h = Holder { value: &text };
    println!("{}", h.value);
}
This code defines a struct with a lifetime, creates an instance holding a reference, and prints the referenced string.
Execution Table
StepActionVariable StatesLifetime CheckOutput
1Define struct Holder with lifetime 'aHolder<'a> definedNo references yet
2Create String text = "hello"text = "hello"text owns data
3Create Holder h with value = &texth.value points to texth.value lifetime <= text lifetime
4Print h.valueh.value = "hello"Reference validhello
5End of main, text and h go out of scopetext and h droppedReferences cleaned safely
💡 Execution ends as main function scope ends, all references are valid and dropped safely.
Variable Tracker
VariableStartAfter Step 2After Step 3After Step 4Final
textuninitialized"hello""hello""hello"dropped
h.valueuninitializeduninitialized&text ("hello")&text ("hello")dropped
Key Moments - 3 Insights
Why do we need to specify a lifetime 'a in the struct definition?
Because the struct holds a reference, Rust needs to know how long that reference is valid to prevent dangling pointers. See execution_table step 3 where h.value points to text.
What happens if the referenced data (text) goes out of scope before the struct instance?
Rust will give a compile-time error because the struct's reference would be invalid. In the execution_table, step 5 shows both text and h go out of scope safely.
Can the struct hold a reference without a lifetime annotation?
No, Rust requires explicit lifetime annotations on structs holding references to ensure safety, as shown in step 1.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table at step 3, what does h.value point to?
AThe String text containing "hello"
BAn uninitialized variable
CA copy of the string "hello"
DA dangling pointer
💡 Hint
Check the Variable States column at step 3 in execution_table.
At which step does Rust ensure the reference lifetime is valid?
AStep 1
BStep 4
CStep 3
DStep 5
💡 Hint
Look at the Lifetime Check column in execution_table.
If text was dropped before h, what would happen?
AProgram runs normally
BCompile-time error due to invalid reference
CRuntime panic
Dh.value becomes a copy of text
💡 Hint
Refer to key_moments about lifetime safety and execution_table step 5.
Concept Snapshot
struct Holder<'a> { value: &'a str }  
- 'a is a lifetime parameter
- Ensures reference inside struct lives long enough
- Rust checks lifetimes at compile time
- Prevents dangling references
- Use when struct holds references
Full Transcript
This example shows how Rust uses lifetimes in structs to keep references safe. We define a struct Holder with a lifetime 'a to hold a reference to a string slice. We create a String variable text and then create an instance h of Holder that holds a reference to text. Rust ensures that h's reference does not outlive text. When we print h.value, it safely shows "hello". At the end of main, both text and h go out of scope, and Rust cleans up safely without any dangling references. Lifetimes prevent errors by making sure references inside structs are valid as long as needed but no longer.

Practice

(1/5)
1. What is the main purpose of using lifetimes in Rust structs?
easy
A. To make structs mutable by default
B. To increase the speed of the program
C. To allow structs to own data permanently
D. To tell Rust how long references inside the struct are valid

Solution

  1. Step 1: Understand what lifetimes represent

    Lifetimes describe how long references are valid to prevent invalid memory access.
  2. Step 2: Connect lifetimes to structs

    In structs, lifetimes tell Rust how long the references inside the struct remain valid.
  3. Final Answer:

    To tell Rust how long references inside the struct are valid -> Option D
  4. Quick Check:

    Lifetimes = reference validity [OK]
Hint: Lifetimes track reference validity duration in structs [OK]
Common Mistakes:
  • Thinking lifetimes control program speed
  • Confusing ownership with lifetimes
  • Assuming lifetimes make structs mutable
2. Which of the following is the correct syntax to declare a struct with a lifetime parameter named 'a'?
easy
A. struct Example { data: &str<'a> }
B. struct Example<'a> { data: &'a str }
C. struct Example { data: &'a str }
D. struct Example<'a> { data: &str'a }

Solution

  1. Step 1: Recall lifetime syntax in structs

    Lifetime parameters are declared after the struct name with angle brackets, e.g., 'a.
  2. Step 2: Match correct placement of lifetime

    The lifetime must be declared as 'a after struct name and used before the reference type.
  3. Final Answer:

    struct Example<'a> { data: &'a str } -> Option B
  4. Quick Check:

    Lifetime syntax = struct Name<'a> { field: &'a Type } [OK]
Hint: Lifetime goes after struct name and before reference type [OK]
Common Mistakes:
  • Placing lifetime after &str instead of before
  • Omitting lifetime parameter after struct name
  • Using incorrect lifetime syntax like &str<'a>
3. What will be the output of this Rust code?
struct Holder<'a> {
    value: &'a i32,
}

fn main() {
    let x = 10;
    let h = Holder { value: &x };
    println!("{}", h.value);
}
medium
A. 10
B. Compilation error due to missing lifetime
C. Runtime error: dangling reference
D. 0

Solution

  1. Step 1: Analyze struct and lifetime usage

    The struct Holder has a lifetime 'a for its reference field. The reference &x is valid inside main.
  2. Step 2: Check code execution

    Variable x is 10, h.value references x, so printing h.value outputs 10.
  3. Final Answer:

    10 -> Option A
  4. Quick Check:

    Reference points to 10, so output = 10 [OK]
Hint: Valid lifetime means reference prints correct value [OK]
Common Mistakes:
  • Assuming compilation error without lifetime annotation
  • Expecting runtime error for valid reference
  • Confusing output with zero or default
4. Identify the error in this Rust code:
struct Container<'a> {
    data: &'a str,
}

fn main() {
    let c;
    {
        let s = String::from("hello");
        c = Container { data: &s };
    }
    println!("{}", c.data);
}
medium
A. Error: 's' does not live long enough for 'c'
B. Error: Missing lifetime parameter in struct
C. Error: Cannot print &str directly
D. No error, code runs fine

Solution

  1. Step 1: Understand variable lifetimes

    Variable 's' is created inside inner block and dropped at block end.
  2. Step 2: Analyze reference validity

    Container 'c' holds reference to 's', but 's' is dropped before 'c' is used, causing invalid reference.
  3. Final Answer:

    Error: 's' does not live long enough for 'c' -> Option A
  4. Quick Check:

    Reference lifetime shorter than struct usage = error [OK]
Hint: Check if referenced data outlives struct instance [OK]
Common Mistakes:
  • Ignoring inner block scope of 's'
  • Thinking missing lifetime parameter causes error here
  • Assuming printing &str causes error
5. You want to create a struct that holds two string slices with different lifetimes. Which is the correct way to declare it?
hard
A. struct Pair { first: &str, second: &str }
B. struct Pair<'a> { first: &'a str, second: &'a str }
C. struct Pair<'a, 'b> { first: &'a str, second: &'b str }
D. struct Pair<'a> { first: &'a str, second: &str }

Solution

  1. Step 1: Understand multiple lifetimes in structs

    When fields have different lifetimes, declare multiple lifetime parameters.
  2. Step 2: Match declaration to fields

    Each field uses its own lifetime parameter, so struct must declare both 'a and 'b.
  3. Final Answer:

    struct Pair<'a, 'b> { first: &'a str, second: &'b str } -> Option C
  4. Quick Check:

    Different lifetimes need separate parameters [OK]
Hint: Use separate lifetime parameters for different references [OK]
Common Mistakes:
  • Using one lifetime for different lifetime references
  • Omitting lifetime parameters entirely
  • Mixing owned and borrowed types without lifetimes
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard