to_owned Example (Moved Value Tips)Learn ways to fix the moved value error by using to_owned or Arc references.
This page was last reviewed on Jun 16, 2022.
To owned. In Rust we must understand the concept of moved values, and how to prevent values from moving when not wanted. A program will not even compile with this kind of problem.
In this language, a value like a string can be moved into a Vector, loop, or function. To prevent moving, we can call to owned() or create Arc references.
Example program. This program shows how we might get into an error with moved values. We create the "shared" string and pass it to the push() function on a vector.
And The comment shows some code where we try to push the string to another vector. But this will not compile.
Info The string was moved into the "elements" vector, so we cannot use it in the "elements2" vector.
So To fix the compilation error in this program, we must avoid moving the string into the first vector.
fn main() { let shared = "bird".to_uppercase(); let mut elements = vec![]; elements.push(shared); // Value "shared" was moved here. // let mut elements2 = vec![]; // elements2.push(shared); // Cannot reuse the "shared" value here. println!("DONE"); }
Error text. The Rust compiler carefully explains the problem in the program. The string does not copy itself automatically, as it lacks the Copy trait.
So The string is moved into the first vector. But this causes the string to not be available for use in the second vector.
error[E0382]: use of moved value: shared move occurs because shared has type String, which does not implement the Copy trait ... value moved here ... value used here after move
Example, to owned. We can copy the string into the first vector, which prevents it from moving there. We can use the "to owned" function to copy and transfer ownership.
Tip This Rust program compiles with no errors. But it causes the string to be copied, so it exists in 2 places.
fn main() { let shared = "bird".to_uppercase(); let mut elements = vec![]; elements.push(shared.to_owned()); // Copy into this vector, without moving. let mut elements2 = vec![]; elements2.push(shared); // Move the element here. println!("DONE"); }
Arc example. Suppose we want to share the same string in the 2 vectors. We can do this by creating an Arc with the string as an argument. Then we clone() the Arc instead of copying a string.
Info The Arc is an atomic reference count. This means is can be used across threads—an Rc is a single-threaded, faster version.
Note The type of the vectors is now an Arc. If the vectors were stored in a struct, or passed to a function, we would need to change the type.
use std::sync::Arc; fn main() { let shared = "bird".to_uppercase(); let arc = Arc::new(shared); let mut elements = vec![]; elements.push(arc.clone()); // Copy Arc into vector. let mut elements2 = vec![]; elements2.push(arc.clone()); println!("DONE: {}", elements[0]); }
Memory notes. Consider a short string—one with just 3 characters. This would be something we could copy to multiple vectors without any performance worries.
However For a long string, like 1000 characters, we would benefit from sharing the data and using Arc references to it.
A summary. For new Rust developers, it is easiest to just copy everything more than needed. Later, we can optimize out copies by adding Arcs to the data that is large enough to be a concern.
Dot Net Perls is a collection of tested code examples. Pages are continually updated to stay current, with code correctness a top priority.
Sam Allen is passionate about computer languages. In the past, his work has been recommended by Apple and Microsoft and he has studied computers at a selective university in the United States.
This page was last updated on Jun 16, 2022 (edit link).
© 2007-2024 Sam Allen.