#[derive(Debug)]
struct Point {
pub x: u32,
pub y: u32,
}
fn main() {
let a = Point{x: 10, y: 12};
let b = a; // Move semantics
// println!("Name: {}, Age: {}", a.x, a.y); // can not use here
println!("Name: {}, Age: {}", b.x, b.y);
}With Copy and Clone the value can be copied:
#[derive(Debug, Copy, Clone)]
struct Point {
pub x: u32,
pub y: u32,
}
fn main() {
let a = Point{x: 10, y: 12};
let b = a; // Copy semantics
println!("Name: {}, Age: {}", a.x, a.y); // allowed
println!("Name: {}, Age: {}", b.x, b.y);
}Clone has two methods clone and clone_from:
#[derive(Debug, Copy, Clone)]
struct Point {
pub x: u32,
pub y: u32,
}
fn main() {
let a = Point{x: 10, y: 12};
let mut b = Point{x: 0, y: 0};
b.clone_from(&a);
println!("Name: {}, Age: {}", a.x, a.y);
println!("Name: {}, Age: {}", b.x, b.y);
}Most scalar types are Copy, immutable references are, too, but String
is not:
fn test_copy<T: Copy>(_t:T) {}
fn main() {
let x: i64 = 12;
let y: String = "abc".to_string();
test_copy(x);
test_copy(y); // Compile error, since String is not Copy
}These are often perceived to be difficult. You have to know 3 things:
- A type
TisSend, if it is safe to send objects of type T between threads. - A type
TisSync, if it is safe to share objects of type T between threads and use them concurrently. - A type
TisSync, if and only if&TisSend.
Contrary to other traits, Send and Sync are usually derived automatically
by the compiler from what it already knows. Most elementary types are both
Send and Sync, but most (smart) pointers are not. A struct is Send
(or Sync resp.), if and only if all its components are Send (or Sync
respectively.
We investigate our smart pointers:
#[derive(Debug)]
struct Person {
pub name: String,
pub age: u32,
}
fn test_copy<T: Copy>(_t: T) { }
fn test_clone<T: Clone>(_t: T) { }
fn test_send<T: Send>(_t: T) { }
fn test_sync<T: Sync>(_t: T) { }
fn main() {
{
let mut b = Box::new(Person{name: "Max".into(), age: 54});
test_copy(b); // error: not copy
test_clone(b); // error: not clone
test_send(b);
test_sync(b);
}
{
let mut b = std::rc::Rc::new(Person{name: "Max".into(), age: 54});
test_copy(b); // error: not copy
test_clone(b);
test_send(b); // error: not send
test_sync(b); // error: not sync
}
{
let mut b = std::sync::Arc::new(Person{name: "Max".into(), age: 54});
test_copy(b); // error: not copy
test_clone(b);
test_send(b);
test_sync(b);
}
{
let b = std::sync::Mutex::new(Person{name: "Max".into(), age: 54});
test_copy(b); // error: not copy
test_clone(b); // error: not clone
test_send(b);
test_sync(b);
let bb = b.lock().unwrap();
test_copy(bb); // error: not copy
test_clone(bb); // error: not clone
test_send(bb); // error: not send
test_sync(bb);
}
{
let b = std::sync::RwLock::new(Person{name: "Max".into(), age: 54});
test_copy(b); // error: not copy
test_clone(b); // error: not clone
test_send(b);
test_sync(b);
{
let bb = b.write().unwrap();
test_copy(bb); // error: not copy
test_clone(bb); // error: not clone
test_send(bb); // error: not send
test_sync(bb);
}
let bbb = b.read().unwrap();
test_copy(bbb); // error: not copy
test_clone(bbb); // error: not clone
test_send(bbb); // error: not send
test_sync(bbb);
}
{
let b = std::cell::RefCell::new(Person{name: "Max".into(), age: 54});
test_copy(b); // error: not copy
test_clone(b); // error: not clone
test_send(b);
test_sync(b); // error: not sync
}
{
let b = std::cell::Cell::new(Person{name: "Max".into(), age: 54});
test_copy(b); // error: not copy
test_clone(b); // error: not clone
test_send(b);
test_sync(b); // error: not sync
}
}Copy: https://doc.rust-lang.org/std/marker/trait.Copy.htmlClone: https://doc.rust-lang.org/std/clone/trait.Clone.html- Rustonomicon
SendandSync: https://doc.rust-lang.org/nomicon/send-and-sync.html Send: https://doc.rust-lang.org/std/marker/trait.Send.htmlSync: https://doc.rust-lang.org/std/marker/trait.Sync.html- Rust book: https://doc.rust-lang.org/book/ch16-03-shared-state.html
- Video: https://youtu.be/B4wjkQZCkt8
- Overview: https://gist.github.com/max-itzpapalotl/18f7675a60f6f9603250367bcb63992e