std::clone::Clone
은 자기 자신의 복사본을 만들 수 있는 타입을 위한 트레이트이다.
trait Clone: Sized {
fn clone(&self) -> Self;
fn clone_from(&mut self. source: &Self) {
*self = source.clone()
}
}
clone
메소드는 self의 복사본을 만들어 리턴한다. Clone 트레이트가 Sized 트레이트를 가지고 있는 이유는 함수는 unsized 값을 반환하지 않기 때문이다.
값을 Clone 할 때는 그 값이 소유한 모든 것이 복사되어야 한다. 그렇기 때문에 clone은 시간과 메모리를 많이 소비할 가능성이 높다.
예를들어 Vec<String>
을 복사하면 벡터만 복사되는것이 아니라 내부의 String
의 요소까지 전부 복사된다.
단 Rc<T>, Arc<T>
는 레퍼런스 카운터만 증가한 새로운 포인터가 리턴된다.
clone_from
메소드는 source 복사본을 가지고 self
의 값을 수정한다.
타입이 같은 경우에는 불필요한 힙 해제와 할당의 과정을 거치지 않고 조금 더 최적화된 작업을 수행할 수 있다.
다만 Clone
을 구현할 때 대상이 되는 타입의 필드나 요소를 간단히 clone해서 얻은 복사본으로 새로운 값을 만들 수 있다면 굳이 직접 구현할 필요는 없다. 다만 #[derive(Clone)]
을 해당 타입 위에 정의하도록 하자
표준 라이브러리에서 복사해도 되는 타입들은 대부분 다 Clone을 구현하고 있다. (bool, i32
등)
clone은 절대 실패해서는 안된다. std::fs::File
값은 타입은 복사할 수 있지만 메모리 등이 부족하면 실패 할 수 있다. 그러므로 Clone을 구현하지 않는데, 다만 Result
를 반환하는 try_clone
메소드를 사용해서 실패 여부를 알 수 있다.
std::marker::Copy
를 구현하는 트레이트
trait Copy: Clone{}
단 Copy는 바이트 단위의 얕은 복사만 수행하는 타입에서만 사용할 수 있다. 힙 할당이나 운영체제 등에서는 사용할 수 없다. Drop
트레이트를 가지고 있는 모든 타입은 Copy
가 될 수 없다.
Clone과 마찬가지로 Copy도 #[derive(Copy)]
를 사용하여 Rust에게 대신 구현하도록 요청할 수 있다. #[derive(Clone, Copy)]
를 주로 많이 사용한다.
Copy는 신중히 사용해야 한다. 타입이 쓰기 수월할지는 모르겠으나, 구현에는 상당한 어려움이 따를 수 있다. 복사비용 역시 클 수 있음을 유의하자.