9.8 Structs and Ownership

Ownership rules apply consistently to structs and their fields.

9.8.1 Owned Fields

Structs typically own their fields. When the struct goes out of scope, it drops its owned fields, freeing resources (like the memory held by a String).

struct DataContainer {
    id: u32,      // Copy type
    data: String, // Owned, non-Copy type
}

fn main() {
    {
        let container = DataContainer {
            id: 1,
            data: String::from("Owned data"),
        };
        println!("Container created with id: {}", container.id);
    } // `container` goes out of scope. `container.data` (the String) is dropped.
    println!("Container dropped.");
}

Assignment of structs follows ownership rules: if the struct type implements Copy, assignment copies the bits. If not, assignment moves ownership.

9.8.2 Fields Containing References (Borrowing)

Structs can hold references, borrowing data owned elsewhere. Lifetime annotations ('a) are required to ensure references don’t outlive the data they point to.

// `'a` ensures references inside PersonView live at least as long as PersonView.
struct PersonView<'a> {
    name: &'a str, // Borrows a string slice
    age: &'a u8,   // Borrows a reference to a u8
}

fn main() {
    let name_data = String::from("Alice");
    let age_data: u8 = 30;
    let person_view: PersonView;

    { // Inner scope
        person_view = PersonView {
            name: &name_data, // Borrow name_data
            age: &age_data,   // Borrow age_data
        };
        // Valid because name_data and age_data outlive person_view within this scope
        println!("View: Name = {}, Age = {}", person_view.name, *person_view.age);
    } // `person_view` goes out of scope here. Borrows end.

    println!("Original name: {}, Original age: {}", name_data, age_data);
}

Lifetimes prevent dangling pointers, a major safety feature compared to manual pointer management in C.