Returning a pointer from a function


#1

If I create a variable in a function and returns it, then the caller can use this variable. I’m assuming this is because the value is copied?

What if I want a function to create a variable, and return a pointer to it, giving the ownership of that variable to the caller? Is this possible? Is there ea way to do this with lifetimes?

I’m trying to do this here, but it’s not compiling. Is it just tha tthe syntax is wrong here, or is it not possible at all:

fn main() {
    println!("I can show you {}", what04());
}

fn what04<'a>() -> &'a str {
    let mut what = "the".to_string();
    what.push_str(" world. - 4.");
    what.split_at(what.len()).0
}

#2

The reason you can’t do this is because bindings (variables) that you define in a function only live for as long as the function is executing. This isn’t specifically a Rust semantic but really a more general semantic of how (most or all?) modern computers work. When a function is called, a block of memory is created for that function to store temporary data in, called “a function stack.” When that function finishes, this function stack is, for all intents and purposes, “destroyed” by the operating system, invalidating whatever was contained within it so that the memory can be reused by other functions in the future.

In order to return a value (indeed, any value) from a function, it has to be either copied to a memory location that the function’s caller has access to, or placed in a special memory location called “the heap,” which is one particular place that each of your functions has access to and isn’t destroyed the same way that a function stack is.

You thus have two possible solutions:

  1. Pass a mutable reference as an argument to your function and use that to copy the value you want to create into the caller’s memory space.
  2. Store the data you created on the heap, so that you can return a reference to that location instead.

The easier way, in my opinion, though certainly slightly less efficient (for reasons you probably don’t need to worry about right now) is to go with option 2 and store your string on the heap. Fortunately, Rust makes this easy with the String type. You can copy a &str onto the heap and get a String as a result by simply calling the to_owned() method on a &str. Your example code could thus be rewritten to:

fn main() {
    println!("I can show you {}", what04());
}

fn what04<'a>() -> String {
    let mut what = "the".to_string();
    what.push_str(" world. - 4.");
    what.split_at(what.len()).0.to_owned()
}

Now the return value of what04 is no longer a &str, but you can actually tell Rust to treat it like one by taking a borrowed reference to your string.

Hope this helps.