[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

 

std::marker::Copy - Rust

#[lang = "copy"]pub trait Copy: Clone { } Types whose values can be duplicated simply by copying bits. By default, variable bindings have 'move semantics.' In other words: #[derive(Debug)] struct Foo; let x = Foo; let y = x; Run However, if a type implemen

doc.rust-lang.org

 

'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

+ Recent posts