Выбрать главу

// Print [2, 3, 4] in arbitrary order.

println!("Intersection: {:?}", a.intersection(&b).collect::<Vec<&i32>>());

// Print [1, 5]

println!("Symmetric Difference: {:?}",

a.symmetric_difference(&b).collect::<Vec<&i32>>());

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

(Examples are adapted from the documentation.)

Rc

When multiple ownership is needed, Rc(Reference Counting) can be used. Rc keeps track of the number of the references which means the number of owners of the value wrapped inside an Rc.

Reference count of an Rc increases by 1 whenever an Rc is cloned, and decreases by 1 whenever one cloned Rc is dropped out of the scope. When an Rc's reference count becomes zero, which means there are no owners remained, both the Rc and the value are all dropped.

Cloning an Rc never performs a deep copy. Cloning creates just another pointer to the wrapped value, and increments the count.

use std::rc::Rc;

fn main() {

let rc_examples = "Rc examples".to_string();

{

println!("--- rc_a is created ---");

let rc_a: Rc<String> = Rc::new(rc_examples);

println!("Reference Count of rc_a: {}", Rc::strong_count(&rc_a));

{

println!("--- rc_a is cloned to rc_b ---");

let rc_b: Rc<String> = Rc::clone(&rc_a);

println!("Reference Count of rc_b: {}", Rc::strong_count(&rc_b));

println!("Reference Count of rc_a: {}", Rc::strong_count(&rc_a));

// Two `Rc`s are equal if their inner values are equal

println!("rc_a and rc_b are equaclass="underline" {}", rc_a.eq(&rc_b));

// We can use methods of a value directly

println!("Length of the value inside rc_a: {}", rc_a.len());

println!("Value of rc_b: {}", rc_b);

println!("--- rc_b is dropped out of scope ---");

}

println!("Reference Count of rc_a: {}", Rc::strong_count(&rc_a));

println!("--- rc_a is dropped out of scope ---");

}

// Error! `rc_examples` already moved into `rc_a`

// And when `rc_a` is dropped, `rc_examples` is dropped together

// println!("rc_examples: {}", rc_examples);

// TODO ^ Try uncommenting this line

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

std::rc and std::sync::arc.

Arc

When shared ownership between threads is needed, Arc(Atomic Reference Counted) can be used. This struct, via the Clone implementation can create a reference pointer for the location of a value in the memory heap while increasing the reference counter. As it shares ownership between threads, when the last reference pointer to a value is out of scope, the variable is dropped.

fn main() {

use std::sync::Arc;

use std::thread;

// This variable declaration is where its value is specified.

let apple = Arc::new("the same apple");

for _ in 0..10 {

// Here there is no value specification as it is a pointer to a reference

// in the memory heap.

let apple = Arc::clone(&apple);

thread::spawn(move || {

// As Arc was used, threads can be spawned using the value allocated

// in the Arc variable pointer's location.

println!("{:?}", apple);

});

}

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Many other types are provided by the std library to support things such as:

   • Threads

   • Channels

   • File I/O

These expand beyond what the primitives provide.

primitives and the std library

Rust provides a mechanism for spawning native OS threads via the spawn function, the argument of this function is a moving closure.