Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I transfer ownership of strings?

Tags:

rust

I am new to Rust and have run into a problem similar to the following a few times:

fn main() {
    let mut as_str: Vec<&String> = Vec::new();
    for i in [1, 2, 3, 4, 5].iter() {
        let i_str = i.to_string();
        as_str.push(&i_str);
    }
}

Which yields the following error:

<anon>:6:22: 6:27 error: `i_str` does not live long enough
<anon>:6         as_str.push(&i_str);
                          ^~~~~

How do I transfer ownership of the string to the vector (do not want to copy)? Do I need a lifetime? Should it be a str or a String (supposing I do not want to mutate the items themselves in the vector)?

like image 600
gnash Avatar asked Aug 21 '15 04:08

gnash


People also ask

How do you pass ownership in Rust?

When doing assignments ( let x = y ) or passing function arguments by value ( foo(x) ), the ownership of the resources is transferred. In Rust-speak, this is known as a move. After moving resources, the previous owner can no longer be used.

How does Rust track ownership?

Rust verifies the ownership rules using the borrow checker. The borrow checker verifies the ownership model and decides if a value in memory (stack or heap) is out of scope or not. If a value is out of its scope, it's not accessible to other parts of the program unless it's borrowed.


1 Answers

Give the vector a String, not a reference to one. A Foo is owned, a &Foo is borrowed.

fn main() {
    let mut as_str: Vec<String> = Vec::new();
    for i in [1, 2, 3, 4, 5].iter() {
        let i_str = i.to_string();
        as_str.push(i_str);
    }
}

In your example, you are allocating a String inside the for loop body, then taking a reference to it. Since nothing owns the String, it is dropped at the end of the loop body. That means that any references would become invalid. Rust prevents this memory safety violation.

In the real world, you'd never need to specify the type here, type inference is enough:

fn main() {
    let mut as_str = Vec::new();
    for i in [1, 2, 3, 4, 5].iter() {
        let i_str = i.to_string();
        as_str.push(i_str);
    }
}

And you'd probably use map to convert one slice of things to another:

fn main() {
    let as_str: Vec<_> = [1, 2, 3, 4, 5].iter().map(|i| i.to_string()).collect();
}

Incidentally, it never makes sense to have a &String; you might as well have a &str.

like image 59
Shepmaster Avatar answered Sep 28 '22 19:09

Shepmaster