HOW smart pointer RC is helpful incase of datatypes that use copy trait

In the case of data types that do not uses copy trait there smart pointer RC becomes
very helpful and efficient.

EXAMPLE WITH RC:

use std::rc::Rc;
use std::ops::Deref;

#[derive(Debug)]
struct ComplexData {
    data: i32,
}

fn transform_data(data: Rc<ComplexData>) -> Rc<ComplexData> {
    let transformed = Rc::new(ComplexData { data: data.deref().data * 2 });
    transformed
}

fn main() {
    let data = Rc::new(ComplexData { data: 5 });
    let transformed_data = transform_data(data.clone());
    println!("Data: {:?}", data);
    println!("Transformed data: {:?}", transformed_data);
}

here, the transform_data function takes ownership of the Rc instance The transformed value is then returned as a new Rc instance.then The main function creates the original Rc instance and passes it to transform_data, which takes ownership of the data.

In this way, the original data remains unchanged and both the original and transformed data can be used simultaneously without borrowing.

EXAMPLE WITHOUT RC:
Without RC we can not keep the original data unchanged.

use std::rc::Rc;

#[derive(Debug)]
struct ComplexData {
    data: i32,
}

fn transform_data(data: ComplexData) -> ComplexData {
    let transformed = ComplexData { data: data.data * 2 };
    transformed
}

fn main() {
    let data = ComplexData { data: 5 };
    let transformed_data = transform_data(data);
    println!("Data: {:?}", data);
    println!("Transformed data: {:?}", transformed_data);
}

This use case of RC is pretty clear.

But In case of datatype that uses copy traits. RC do not seems to be that helpful. because we can achieve same result without RC because we are using datatype that posses copy trait
here is the example

EXAMPLE WITH RC:

use std::rc::Rc;
use std::ops::Deref;

fn transform_data(data: Rc<i32>) -> Rc<i32> {
    let transformed = Rc::new(data.deref() * 2);
    transformed
}

fn main() {
    let data = Rc::new(5);
    let transformed_data = transform_data(data.clone());
    println!("Data: {:?}", data);
    println!("Transformed data: {:?}", transformed_data);
}

EXAMPLE WITHOUT RC:

fn transform_data(data: i32) -> i32 {
     let transformed = data * 2;
     transformed
}

fn main(){
    let data = 5;
    let transformed_data = transform_data(data);
    println!("Data: {:?}", data);
    println!("Transformed data: {:?}", transformed_data);
}

I want to know If there is any advantage of RC in the case of datatype that use copy trait.

I'm not sure I fully understand what you're asking, but if transform_data only reads from its parameter, it would be easiest to take a borrow:

fn transform_data(data: &ComplexData) -> ComplexData {
    todo!()
}
1 Like

If it's large and you would have many copies of it, Rc<_> may be more efficient.

If you need shared mutability, Rc<RefCell<_>> lets you change a value and everyone who has a clone of the Rc will also see the change.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.