여러 변수가 소유권을 공유할 수 있는 포인터이다. C++의 shared_ptr에 해당한다. 또한 python에서 garbafe collector가 리스트를 관리하는 방법이기도 하다.
사진과 같이 list에는 reference count가 몇 개의 변수가 리스트를 참조하고 있는지 count하고 0이 된다면 garbage collector가 리스트를 삭제한다. Rust에서는 String을 담은 Vec가 어떻게 작동하는지 보자.
와 같이 소유권이 옮겨 가면서 stack에 새로운 포인터 변수를 추가하게 된다.
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>
는 읽기 전용으로 데이터를 공유하도록 허용해준다.
이렇게 유용한 정보를 공유해주셔서 감사합니다.