[0]
Rust의 std에서 제공하는 Copy trait과 Clone trait에 대해 알아보자.
[1]
#[derive(Debug)]
struct MyStruct{
x:i32,
y:i32,
}
fn main(){
let x = MyStruct{x:1,y:2};
let y = x;
println!("{:?}",y);
println!("{:?}",x); // error here!
}
y = x에서 x의 소유권은 y에게로 옮겨진다. 따라서 x는 더 이상 소유권이 없기 때문에 x에 접근을 하게 되면 에러가 발생한다. 이를 해결하기 위해선, y = &x와 같이 레퍼런스를 전달할 수도 있지만, 상황에 따라선 x의 값을 복사해서 y에 넘겨주어야 할 때가 있을 수 있다. 이런 경우에 std의 Copy trait과 Clone trait을 이용할 수 있다.
[2]
먼저 Copy trait에 대해 알아보자. Copy는 다음과 같이 derive를 이용해 간단히 이용할 수 있다. 이 경우 반드시 Clone trait도 함께 구현해야 한다.
#[derive(Debug, Copy, Clone)]
struct MyStruct{
x:i32,
y:i32,
}
fn main(){
let x = MyStruct{x:1,y:2};
let y = x;
println!("{:?}",y);
println!("{:?}",x);
}
혹은 impl을 통해 직접 구현할 수도 있다.
#[derive(Debug)]
struct MyStruct{
x:i32,
y:i32,
}
impl Copy for MyStruct { }
impl Clone for MyStruct {
fn clone(&self) -> MyStruct {
*self
}
}
fn main(){
let x = MyStruct{x:1,y:2};
let y = x;
println!("{:?}",y);
println!("{:?}",x);
}
Copy trait은 오버로딩할 수 없다. 즉, Copy의 행동을 바꿀 수 없으며, Copy trait은 항상 메모리 카피를 수행하게 된다. 또 한 가지 중요한 점으로, struct의 멤버 중 하나라도 Copy trait이 구현되어 있지 않다면, 해당 struct는 Copy를 구현할 수 없다. 기본적으로 스택에 할당되는 Rust primitive들은 모두 Copy를 구현한다. i32, u64 등의 타입이 이에 해당한다. 하지만 Vec<T>나 String과 같은 힙에 할당되는 타입들은 Copy를 구현하지 않는다. 이러한 타입들은 struct내에 해당 오브젝트를 가리키는 주소 값만이 저장되기 때문이다. C에서 shallow copy와 deep copy의 차이점을 생각하면 된다. 즉 shallow copy만으로 모든 컨텐츠를 복사할 수 있는 경우에만 Copy trait 구현이 가능하다. deep copy가 필요할 경우에는 Clone trait을 사용해야 한다.
[3]
Clone trait은 Copy trait의 superstrait이다. Copy와 마찬가지로 derive를 통해 구현할 수 있다. 또한 impl을 통해서도 구현할 수 있는데, Copy와 다르게 오버라이딩이 가능하다.
#[derive(Debug)]
struct MyStruct{
x:i32,
y:i32,
}
impl Clone for MyStruct {
fn clone(&self) -> MyStruct {
println!("clone is called!");
MyStruct{x:self.x, y:self.y}
}
}
fn main(){
let x = MyStruct{x:1,y:2};
let y = x.clone();
println!("{:?}",y);
println!("{:?}",x);
}
오버라이딩이 가능하기 때문에 원한다면 위처럼 println을 찍는 등의 새로운 기능을 추가할 수 있다. Copy와의 큰 차이점은 위에서 x.clone()을 한 것처럼 명시적으로 호출해야 한다는 점이다.
[참고]
https://doc.rust-lang.org/std/marker/trait.Copy.html
'Computer Science > Rust' 카테고리의 다른 글
Rust의 trait object (0) | 2020.08.02 |
---|---|
Rust의 async/await와 Future (0) | 2020.07.21 |
Rust의 스마트 포인터 (0) | 2020.05.20 |
Rust의 lifetime parameter (0) | 2020.05.05 |
Rust의 Trait (1) | 2020.03.10 |