Rc<T>
What is the Rc<T>
- Reference-counted Smart Pointer?
Rc<T>
- Reference-counted Smart Pointer?💡 Rc<T>
stands for reference-counted smart pointer that enables multiple ownership of the same data of type T
. It provides a way to share ownership between different parts of a program without copying the data itself and keeps track of the number of references to a value, and the value is deallocated only when the reference count drops to zero.
Unlike regular references (&T
) which can only have one owner, Rc<T>
allows multiple owners to own the same data. This is useful when you need to share data between different parts of your program without transferring ownership and avoid duplication when the data needs to be accessed from multiple locations.
Rc<T>
maintains a reference count, which keeps track of how many Rc
instances point to the same value. When the last Rc
pointing to the value goes out of scope, the value is automatically deallocated, preventing memory leak.
Rc<T>
only allows immutable references to the data it wraps. If you need to mutate the data, you should use RefCell<T>
in combination with Rc<T>
to achieve interior mutability.
Using Box<T>
To Share Ownership
Box<T>
To Share OwnershipIn this example, we’re building a Cache
for memoizing the data that allows other services to use it for their memoization.
We define a simple struct named Cache
. It doesn't have any fields.
We define two structs UserService
and PostService
, each containing a single field named cache
of type Cache
.
In the main function, we create an instance of Cache
and assign it to the variable cache.
We initialize an instance of UserService
with the cache instance. Here, the ownership of the cache instance is moved to user_service.cache
.
In the next line, we initialize an instance of PostService
with the cache instance. The code attempts to move the cache
instance again into post_service.cache
, but cache
has already been moved into user_service.cache
, and Rust enforces single ownership of values by default, therefore, the error occurs.
The problem here is:
Move Semantics: In Rust, when you assign or pass a value to another variable or function, the ownership of that value is transferred (moved). After a move, the original variable can no longer be used.
Ownership Rules: Since
cache
is moved intouser_service
, it can no longer be used to createpost_service
. Attempting to usecache
after it has been moved results in a compilation error becausecache
no longer owns theCache
instance.
To share the Cache
instance between UserService
and PostService
, you need to use reference-counted smart pointers (Rc<T>
) to allow multiple ownership.
In this code, we wrap the Cache
instance inside both the UserService
and PostService
using Rc
smart pointer. This means they share ownership of a single Cache
instance.
We also implement a cache_data
method that simply returns a string "Cache the data" (presumably a placeholder for actual caching logic).
In the main function, we create a Cache
instance and wrap it in Rc::new(Cache {})
to enable reference counting.
Two services, user_service
and post_service
, are created. They both receive a cloned reference (Rc::clone(&cache)
) to the shared cache. By cloning the Rc<Cache>
, you create additional references to the same Cache
instance. This allows both UserService
and PostService
to own and use the same Cache
instance.
When we clone an Rc
, it increments a reference count instead of copying the actual value.
Finally, cache_data
methods are called on both services. Since they share the same cache instance, both calls will ultimately execute the cache_data
method defined in the Cache
struct, potentially printing "Cache the data" twice.
How Rc executes the reference count of the Cache instance:
Initially, the reference count of the
Cache
instance is 1 when it's wrapped inRc::new(Cache {})
.When
user_service
andpost_service
are created, they both clone the existingRc<Cache>
, incrementing the reference count to 2.Since both services share the same
Rc<Cache>
, they are essentially pointing to the same underlyingCache
instance.When
main
goes out of scope, bothuser_service
andpost_service
will also eventually go out of scope.As each
Rc<Cache>
in these services goes out of scope, the reference count is decremented by 1 (once for each service).If there are no other owners of the
Cache
instance, the reference count will finally reach zero, and theCache
instance will be deallocated.
Last updated