1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-04-25 16:54:32 +02:00

Use explicit Arc::clone instead of calling .clone() method (#596)

This is to highlight that the clones are cheap: they run custom logic
in the reference counted type, they don’t do a deep clone.
This commit is contained in:
Martin Geisler 2023-04-27 14:46:09 -07:00 committed by GitHub
parent 6ade739651
commit b051b04afa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 8 additions and 8 deletions

View File

@ -1,6 +1,6 @@
# `Arc` # `Arc`
[`Arc<T>`][1] allows shared read-only access via its `clone` method: [`Arc<T>`][1] allows shared read-only access via `Arc::clone`:
```rust,editable ```rust,editable
use std::thread; use std::thread;
@ -10,7 +10,7 @@ fn main() {
let v = Arc::new(vec![10, 20, 30]); let v = Arc::new(vec![10, 20, 30]);
let mut handles = Vec::new(); let mut handles = Vec::new();
for _ in 1..5 { for _ in 1..5 {
let v = v.clone(); let v = Arc::clone(&v);
handles.push(thread::spawn(move || { handles.push(thread::spawn(move || {
let thread_id = thread::current().id(); let thread_id = thread::current().id();
println!("{thread_id:?}: {v:?}"); println!("{thread_id:?}: {v:?}");

View File

@ -7,7 +7,7 @@ use std::thread;
// use std::sync::{Arc, Mutex}; // use std::sync::{Arc, Mutex};
fn main() { fn main() {
let mut v = vec![10, 20, 30]; let v = vec![10, 20, 30];
let handle = thread::spawn(|| { let handle = thread::spawn(|| {
v.push(10); v.push(10);
}); });
@ -29,7 +29,7 @@ use std::thread;
fn main() { fn main() {
let v = Arc::new(Mutex::new(vec![10, 20, 30])); let v = Arc::new(Mutex::new(vec![10, 20, 30]));
let v2 = v.clone(); let v2 = Arc::clone(&v);
let handle = thread::spawn(move || { let handle = thread::spawn(move || {
let mut v2 = v2.lock().unwrap(); let mut v2 = v2.lock().unwrap();
v2.push(10); v2.push(10);

View File

@ -8,7 +8,7 @@ use std::rc::Rc;
fn main() { fn main() {
let mut a = Rc::new(10); let mut a = Rc::new(10);
let mut b = a.clone(); let mut b = Rc::clone(&a);
println!("a: {a}"); println!("a: {a}");
println!("b: {b}"); println!("b: {b}");
@ -28,13 +28,13 @@ fn main() {
<details> <details>
* `Rc`'s Count ensures that its contained value is valid for as long as there are references. * `Rc`'s count ensures that its contained value is valid for as long as there are references.
* Like C++'s `std::shared_ptr`. * Like C++'s `std::shared_ptr`.
* `clone` is cheap: it creates a pointer to the same allocation and increases the reference count. Does not make a deep clone and can generally be ignored when looking for performance issues in code. * `Rc::clone` is cheap: it creates a pointer to the same allocation and increases the reference count. Does not make a deep clone and can generally be ignored when looking for performance issues in code.
* `make_mut` actually clones the inner value if necessary ("clone-on-write") and returns a mutable reference. * `make_mut` actually clones the inner value if necessary ("clone-on-write") and returns a mutable reference.
* Use `Rc::strong_count` to check the reference count. * Use `Rc::strong_count` to check the reference count.
* Compare the different datatypes mentioned. `Box` enables (im)mutable borrows that are enforced at compile time. `RefCell` enables (im)mutable borrows that are enforced at run time and will panic if it fails at runtime. * Compare the different datatypes mentioned. `Box` enables (im)mutable borrows that are enforced at compile time. `RefCell` enables (im)mutable borrows that are enforced at run time and will panic if it fails at runtime.
* You can `downgrade()` a `Rc` into a *weakly reference-counted* object to * `Rc::downgrade` gives you a *weakly reference-counted* object to
create cycles that will be dropped properly (likely in combination with create cycles that will be dropped properly (likely in combination with
`RefCell`). `RefCell`).