Utility Traits - Drop

이정후·2023년 8월 8일
0

Rust

목록 보기
7/13
post-thumbnail

Utility Traits

Rust의 표준 라이브러리에 있는 다양한 트레이트들 중에서 러스트를 사용함에 있어 큰 영향을 미치는 것들을 가리킨다고 한다. 러스트답다 고 평가받을 만한 코드나 인터페이스를 설계하기 위해서는 꼭 알아야 할 것 같아서 정리하게 되었다.

Drop, Deref, DerefMut, From, Into,Sized, Copy 등등에 대해서 공부하고 알아보자

Drop

기본적으로 Rust에서는 값의 소유자가 사라지면 그 값을 드롭(drop)한다. 이때 그 값이 소유한 다른 값들과 Heap 등 관련된 자원과 메모리는 드롭 과정에서 전부 해제된다. 드롭은 변수가 범위를 벗어날 때, 표현식의 실행문이 끝날때 등등 다양한 상황에서 일어난다.

대부분의 경우에는 Rust에서 값을 알아서 드롭해 준다.

struct Marvel {
    name: String,
    nickname: Vec<String>
}

Marvel은 이름을 저장하는 문자열과 닉네임의 요소를 저장하기 위한 벡터 힙을 가지고 있다. 기본적으로 사용자가 따로 정의 하지 않아도 Marvel이 사용되고 드롭될 때마다 알아서 정리해준다. 그렇지만 원한다면 std::ops::Drop 트레이트를 구현해서 Rust의 드롭 과정에 관여할 수 있다.

trait Drop {
	fn drop(&mut self);
}

기본적인 형태는 위와 같다.

만일 드롭되는 값이 std::ops::Drop을 구현하고 있을 경우, 전부 드롭하기 전에 drop 메소드를 호출한다. 이는 Rust만이 직접 호출할 수 있다.

이 호출 시점은 해당 값의 필드나 요소가 아직 드롭되기 전이므로 메소드로 전달되는 값은 항상 값이 초기화된 상태로 넘어오게 된다.

impl Drop for Marvel {
	fn drop(&mut self) {
    	println!("드롭!! {}", self.name)
    
    	if !self.nickname.is_empty() {
        	println!(" (AKA {})", self.nickname.join(", "))
        }
        println!("");
    }
}
// main.rs

fn main() {
    let mut a = Marvel {
        name: "아이언맨".to_string(),
        nickname: vec!["3000만큼".to_string(), "따뜻한 강철 심장".to_string()]
    };

    println!("시작");
    a = Marvel {
        name: "토르".to_string(),
        nickname: vec!["천둥의 신".to_string(), "묠니르".to_string()]
    };
    println!("종료");
} 

두번 째 a에 값을 새로 배정하면 첫번 째 값이 드롭되고 a가 실행을 완료해서 범위를 벗어나게 되면 두번 째 값이 드롭된다.

보이지 않는 손

VecDrop을 구현하고 있다

fn drop(&mut self)

이를 통해서 자신이 가진 요소들을 드롭하고, 힙 할당 메모리를 해제한다. String은 내부적으로 Vec<u8>을 써서 자신의 텍스트를 보관하기 때문에 Drop을 따로 구현하고 있지 않으며 문자들을 해제하는 일은 Vec에게 위임하여 처리한다.

Rust는 GC가 없다.

GC(Garbage Collector)가 없는 Rust는 개발자가 직접 메모리 할당과 해제를 제어할 수 있는 기능을 제공한다. Rust만의 소유권, 참조 관리(빌림 규칙) 등을 통해 메모리 안정성을 보장하고 개발자는 객체의 소유권을 명확하게 지정하여 해당 객체가 사용되지 않을 때 자동으로 컴파일러가 해체할 수 있게 해야한다.

profile
꾸준하게

0개의 댓글