러스트의 표준 컬렉션(예: Vec<T>, HashMap<K,V>, HashSet<T> 등)은 컨텐츠에 대한 소유권 원칙을 구현합니다. 이는 컬렉션이 포함하고 있는 모든 객체를 소유하고 있으며, 삭제 시 그 메모리를 해제할 책임이 있음을 의미합니다.
예를 들어, Vec<T>에 넣어진 요소는 벡터로 이동(move)하고, 이후 벡터가 이것을 소유합니다:
let s = String::from("hi"); let mut v = Vec::new(); v.push(s); // s는 이제 이동되어 사용할 수 없음
컬렉션에 복사 가능한 값이 포함되어 있으면 이를 복사하는 반면, 이동 가능한 경우 소유권이 이전됩니다. 두 장소에서 원래 값을 유지해야 할 경우 요소나 컬렉션을 복제해야 합니다, 예를 들어:
let name = String::from("Olga"); let mut v = Vec::new(); v.push(name.clone()); println!("{}", name); // name은 여전히 접근 가능하며, clone 되었기 때문임
HashMap에 요소를 삽입할 때 이동 가능한 데이터 유형(예: String)을 키로 사용하는 경우 어떻게 되나요? HashMap::insert()에 전달한 이후 원래 키는 여전히 사용 가능할까요?
종종 잘못된 대답: "원래 키는 삽입 후에도 사용 가능하다"고 합니다.
실제로는 키와 값의 소유권이 HashMap에 전달되며, 삽입 후에는 사전 복제 없이 사용할 수 없습니다:
let key = String::from("id"); let mut map = std::collections::HashMap::new(); map.insert(key, 42); // key는 더 이상 사용 불가능
key에 접근하려고 하면 컴파일 에러가 발생합니다.
이야기 개발자가 Vec에 삽입한 후 이동된 객체를 사용하려고 하였고, "move 후 사용된 값" 오류를 발생시켰으며, Vector가 이제 그것을 소유하고 있다는 사실을 이해하지 못했습니다.
이야기 HashMap을 사용할 때 문자열 키를 복제하는 것을 잊어서 다른 곳에서 사용하지 못하게 되었고, 이는 코드의 상당한 리팩토링을 요구했습니다.
이야기 한 프로젝트에서 함수 밖에서 벡터의 내부 요소에 대한 참조를 반환하려고 시도했으며, 벡터 크기 변경 시 참조가 무효화된다는 것을 잊어버렸습니다. 이는 dangling references 및 실행 중 충돌(panic)을 초래했습니다.