Rust – Keywords on moving closures on the vector

I was told that when the move keyword is used in a closure, the closure takes ownership of a copy of the variable in its environment. But this code will not compile:

use std::thread;
use std::time::Duration;

fn main() {
let mut data = vec![1, 2, 3];

for i in 0..3 {
thread::spawn(move || {
data[i] + = 1;
});
}

thread::sleep(Duration::from_millis(50));
}

error The message is

8:17 error: capture of moved value: `data`
data[i] += 1;
^~~~< /pre>

There are some explanations for this

Rust knows this wouldn't be safe! If we had a reference to data in each thread, and the thread takes ownership of the reference, we'd have three owners!

Does this mean that the copy only copies the metadata on the stack and not the actual data on the heap? In other words, the copy reference is because the data type itself is essentially a reference type, not a reference created by the & mut syntax. For all data types, does the move keyword copy data on the stack? Therefore, when it is of type like i32, it is copied by value, and if it is of type vector, it is copied by reference.

My original intention was to understand the exact behavior of the move keyword. Take a closer look. After the Rust documentation, I think it follows the move semantics of universal variable binding. In this case, the ownership of "data" can only be transferred once. Although changing from 0..3 to 0..1 makes no difference. Indeed, The metadata on the stack is copied, not the heap data.

Does it mean that the copy only copies the metadata on the stack not
the real data on the heap? In other words, the reference is copied
because the data type itself is a reference type by nature, not
referring to the reference created by &mut syntax. Is it true for all
data types that the move keyword copies data on the stack? So when it
comes to type like i32 it copies by value, and by reference if it is
type like vector.

When transferring the ownership of variables, deep copying is not performed. All pointers still point to the same value and do not touch the heap memory. The transfer of ownership is by design An inexpensive operation. If you need a deep copy, you can explicitly call the clone method on Vec. Some types that are cheap to clone (such as i32) implement the Copy trait, which means if you try to pass ownership of the same value to For multiple targets, clone will be called automatically.

My original intention is to understand the exact behavior of the move
keyword. After a closer look at the Rust docs, I think it follows move
semantics of general variable bindings. In this case, the ownership of
“data” can only be transferred once. Though change 0..3 to 0 ..1
doesn't make a difference. Also it's true that the metadata on the
stack is copied, not the heap data.

Use 0..1不Works, because the compiler does not check whether the iterable range 0..1 contains only a single element. So using 0..1 can not compile, but completely deleting the for loop is logically equivalent and compiles

use std::thread;
use std::time::Duration;

fn main() {
let mut data = vec! [1, 2, 3];

thread::spawn(move || {
data[0] += 1;
});

thread::sleep(Duration::from_millis(50));
}

If we try to access the data again after passing it to thread::spawn, we will get a compilation Errors, such as errors: use the move value:'data'. This is the role of the move keyword. Since the data has been moved to the closure, the closure is now responsible for releasing its memory. It is worth noting that if there is no move keyword, This code will not compile, because in this case, the data will be deallocated at the end of the main function, but the thread may be longer than the main function.

Someone told I, when using the move keyword in a closure, the closure takes ownership of a copy of the variable in its environment. But this code will not compile:

use std::thread;
use std::time::Dura tion;

fn main() {
let mut data = vec![1, 2, 3];

for i in 0..3 {< br /> thread::spawn(move || {
data[i] += 1;
});
}

thread::sleep(Duration ::from_millis(50));
}

The error message is

8:17 error: capture of moved value: `data` 
data[i] += 1;
^~~~

There are some explanations for this

Rust knows this wouldn't be safe! If we had a reference to data in each thread, and the thread takes ownership of the reference, we'd have three owners!

Does this mean The copy only copies the metadata on the stack and not the actual data on the heap? In other words, the copy reference is because the data type itself is essentially a reference type, not a reference created by the & mut syntax. For all data types, does the move keyword copy data on the stack? Therefore, when it is of type like i32, it is copied by value, and if it is of type vector, it is copied by reference.

My original intention was to understand the exact behavior of the move keyword. Take a closer look. After the Rust documentation, I think it follows the move semantics of universal variable binding. In this case, the ownership of "data" can only be transferred once. Although changing from 0..3 to 0..1 makes no difference. Indeed, The metadata on the stack is copied, not the heap data.

Does it mean that the copy only copies the metadata on the stack not
the real data on the heap? In other words, the reference is copied
because the data type itself is a reference type by nature, not
referring to the reference created by &mut syntax. Is it true for all
data types that the move keyword copies data on the stack? So when it
comes to type like i32 it copies by value, and by reference if it is
type like vector.

When transferring ownership of variables, deep copying is not performed. All pointers still point to the same value and do not touch the heap memory. Transferring ownership by design is a cheap operation. If you need a deep copy, you can Explicitly call the clone method on Vec. Some types that are cheap to clone (e.g. i32) implement the Copy trait, which means that if you try to pass ownership of the same value to multiple targets, clone will be called automatically.

My original intention is to understand the exact behavior of the move
keyword. After a closer look at the Rust docs, I think it follows move
semantics of general variable bindings. In this case, the ownership of
“data” can only be transferred once. Though change 0..3 to 0..1
doesn't make a difference. Also it's true that the metadata on the
stack is copied, not the heap data.

Using 0..1 does not work because the compiler does not check the iterable range 0. .1 contains only a single element. So using 0..1 cannot be compiled, but completely deleting the for loop is logically equivalent and compiling

use std::thread ;
use std::time::Duration;

fn main() {
let mut data = vec![1, 2, 3];
< br /> thread::spawn(move || {
data[0] += 1;
});

thread::sleep(Duration::from_millis(50 ));
}

If we try to access the data again after passing it to thread::spawn, we will get a compilation error, such as error: using move value:'data'. This is what the move keyword does. Since the data has been moved to the closure, the closure is now responsible for releasing its memory. It is worth noting that this code will not compile without the move keyword, because in this case, The data will be deallocated at the end of the main function, but the thread may be longer than the main function.

Leave a Comment

Your email address will not be published.