[Rust] Rc, Arc (Shared Ownership)에 관해

고승우·2023년 8월 3일
0

Rust

목록 보기
4/16
post-thumbnail

Reference Counting

여러 변수가 소유권을 공유할 수 있는 포인터이다. C++의 shared_ptr에 해당한다. 또한 python에서 garbafe collector가 리스트를 관리하는 방법이기도 하다.

사진과 같이 list에는 reference count가 몇 개의 변수가 리스트를 참조하고 있는지 count하고 0이 된다면 garbage collector가 리스트를 삭제한다. Rust에서는 String을 담은 Vec가 어떻게 작동하는지 보자.


와 같이 소유권이 옮겨 가면서 stack에 새로운 포인터 변수를 추가하게 된다.

Rc (reference counting)

Rc<T>는 value의 shared ownership을 가능하게 해주는 smart pointer다. reference count가 0이 되면 deallocate 된다. Rc<T>의 clone 생성은 reference count를 증가시킨다. Rc::strong_count(& Rc<T>)로 이를 확인할 수 있다.

use std::rc::Rc;

#[derive(Debug)]
pub struct MyString{
    string: String
}
fn main(){
    let a = Rc::new(MyString{string: "Test String".to_string()});
    let b = a.clone();
    println!("{:?}", Rc::strong_count(& b));    // 2
    println!("{:?}", b);                        // "testString"
    println!("{:?}", Rc::strong_count(& b));    // 2
}

위 코드에서 b의 ownership이 소모되지 않았다는 것을 알 수 있다. Rc는 reference라서 소유권을 갖고 있지 않다. 일반 참조자 여러개를 선언할 수 있지만 가변 참조자 하나만 선언할 수 있다는 것을 기억한다면, 의문이 들 것이다. 과연 Rc<T>값을 바꿀 수 있을까?

use std::rc::Rc;

#[derive(Debug)]
pub struct MyString{
    string: String
}

impl MyString{
    fn change(
        &mut self,
        newStr: String
    ){
        self.string = newStr;
    }
}

fn main(){
    let mut a = Rc::new(MyString{string: "Test String".to_string()});
    let mut b = a.clone();
    a.change("Changed String".to_string());
    println!("{:?}", b);
}


예상대로 되지 않는다. Rc<T>는 불변 참조와 비슷하게 적당한다. Rc<T>는 결국 데이터에 접근하고 관리하는 "방법이지" 불변 참조자라고 생각하면 안된다. 하지만 불변 참조자를 통하여, Rc<T>는 읽기 전용으로 데이터를 공유하도록 허용해준다.

profile
٩( ᐛ )و 

1개의 댓글

comment-user-thumbnail
2023년 8월 3일

이렇게 유용한 정보를 공유해주셔서 감사합니다.

답글 달기