Teekin
Teekin

Reputation: 13279

What happens to the ownership of a value returned but not assigned by the calling function?

Consider the following Rust code, slightly modified from examples in The Book.

I'm trying to understand what happens to the value in the second running of function dangle() in the main() function (see comment). I would imagine that because the value isn't assigned to any owner, it gets deallocated, but I've so far failed to find information to confirm that. Otherwise, I would think that calling dangle() repeatedly would constantly allocate more memory without deallocating it. Which is it?

fn main() {
    // Ownership of dangle()'s return value is passed to the variable `thingamabob`.
    let thingamabob = dangle();

    // No ownership specified. Is the return value deallocated here?
    dangle();

    println!("Ref: {}", thingamabob);
}

fn dangle() -> String {
    // Ownership specified.
    let s = String::from("hello");

    // Ownership is passed to calling function.
    s
}

Upvotes: 2

Views: 771

Answers (2)

Dan R
Dan R

Reputation: 1494

In your example, the second call creates an unnamed temporary value whose lifetime ends immediately after that one line of code, so it goes out of scope (and any resources are reclaimed) immediately.

If you bind the value to a name using let, then its lifetime extends until the end of the current lexical scope (closing curly brace).

You can explore some of this yourself by implementing the Drop trait on a simple type to see when its lifetime ends. Here's a small program I made to play with this (playground):

#[derive(Debug)]
struct Thing {
    val: i32,
}

impl Thing {
    fn new(val: i32) -> Self {
        println!("Creating Thing #{}", val);
        Thing { val }
    }

    fn foo(self, val: i32) -> Self {
        Thing::new(val)
    }
}

impl Drop for Thing {
    fn drop(&mut self) {
        println!("Dropping {:?}", self);
    }
}

pub fn main() {
    let _t1 = Thing::new(1);

    Thing::new(2); // dropped immediately

    {
        let t3 = Thing::new(3);

        Thing::new(4).foo(5).foo(6); // all are dropped, in order, as the next one is created

        println!("Doing something with t3: {:?}", t3);
    } // t3 is dropped here
} // _t1 is dropped last

Upvotes: 2

Shepmaster
Shepmaster

Reputation: 430681

When a value has no owner (is not bound to a variable) it goes out of scope. Values that go out of scope are dropped. Dropping a value frees the resources associated with that value.

Anything less would lead to memory leaks, which would be a poor idea in a programming language.

See also:

Upvotes: 3

Related Questions