Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Arrow up icon
GO TO TOP
Hands-On Data Structures and Algorithms with Rust

You're reading from   Hands-On Data Structures and Algorithms with Rust Learn programming techniques to build effective, maintainable, and readable code in Rust 2018

Arrow left icon
Product type Paperback
Published in Jan 2019
Publisher Packt
ISBN-13 9781788995528
Length 316 pages
Edition 1st Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
Claus Matzinger Claus Matzinger
Author Profile Icon Claus Matzinger
Claus Matzinger
Arrow right icon
View More author details
Toc

Table of Contents (15) Chapters Close

Preface 1. Hello Rust! FREE CHAPTER 2. Cargo and Crates 3. Storing Efficiently 4. Lists, Lists, and More Lists 5. Robust Trees 6. Exploring Maps and Sets 7. Collections in Rust 8. Algorithm Evaluation 9. Ordering Things 10. Finding Stuff 11. Random and Combinatorial 12. Algorithms of the Standard Library 13. Assessments 14. Other Books You May Enjoy

Multiple owners

As powerful as single ownership is, it does not work for every use case. Large objects or shared objects that other instances need to own are examples where immutable ownership makes life easier. Consider a function that requires an owned object to be passed in:

#[derive(Debug)]
struct FileName {
name: String,
ext: String
}

fn no_ref_counter() {
let name = String::from("main");
let ext = String::from("rs");

for _ in 0..3 {
println!("{;?}",
FileName {
name: name,
ext: ext
});

}
}

When trying to compile no_ref_counter(), the compiler creates a scope for each iteration of the loop and owns any value that is used within it. This works exactly once, since afterward, the variable has been moved and is inaccessible for subsequent iterations.

Consequently, these values (in this case, name and ext) are gone and compilation will yield two errors, one for each "second" move of a string:

error[E0382]: use of moved value: `name`
--> src/main.rs:63:33
|
63 | let _ = FileName { name: name, ext: ext };
| ^^^^ value moved here in previous iteration of loop
|
= note: move occurs because `name` has type `std::string::String`, which does not implement the `Copy` trait

error[E0382]: use of moved value: `ext`
--> src/main.rs:63:44
|
63 | let _ = FileName { name: name, ext: ext };
| ^^^ value moved here in previous iteration of loop
|
= note: move occurs because `ext` has type `std::string::String`, which does not implement the `Copy` trait

One solution is to clone the object in every iteration, but that causes a lot of slow memory allocations. For this, the Rust standard library provides a solution: reference counting.

A reference counter (std::rc::Rc<T>) encapsulates a variable of type T allocated on the heap and returns an immutable reference when created. This reference can be cloned with low overhead (it's only a reference count that is incremented) but never transformed into a mutable reference. Regardless, it acts just like owned data, passing through function calls and property lookups.

While this requires a change to the variable types, a call to clone() is now far cheaper than cloning the data directly:

use std::rc::Rc;

#[derive(Debug)]
struct FileName {
name: Rc<String>,
ext: Rc<String>
}

fn ref_counter() {
let name = Rc::new(String::from("main"));
let ext = Rc::new(String::from("rs")));

for _ in 0..3 {
println!("{;?}",
FileName {
name: name.clone(),
ext: ext.clone()
});

}
}

Running this snippet prints the debug version of the FileName object three times:

FileName { name: "main", ext: "rs" }
FileName { name: "main", ext: "rs" }
FileName { name: "main", ext: "rs" }

This approach works great for single-threaded and immutable scenarios, but will refuse to compile multithreaded code. The solution to this will be discussed in the next section.

You have been reading a chapter from
Hands-On Data Structures and Algorithms with Rust
Published in: Jan 2019
Publisher: Packt
ISBN-13: 9781788995528
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at £13.99/month. Cancel anytime
Visually different images