For Fun

[rust 공식 문서 14일 공부] 13 일차

Jㅐ둥이 2025. 2. 4. 01:00
반응형

15. Smart Pointers

이제 rust에서 지원하는 스마트 포인터 기능에 대해서 공부할 시간입니다.

 

스마트 포인터는 C++, Nim, Zig 등 여러 프로그래밍 언어에서 지원하고 있는 기능입니다.

  • 대표적으로 C++에는 unique_ptr, shared_ptr 등의 스마트 포인터 기능이 있습니다.

rust에서 가장 많이 사용되는 스마트 포인터인 Box, Rc, Ref, RefMut, RefCell 에 대해 공부해보겠습니다.

 

15.1. Using Box<T> to Point to Data on the Heap

Box는 메모리를 heap에 할당하는 것 이외의 기능이 없는 스마트 포인터입니다.

추가적인 기능이 없지만 다음과 같은 상황에서 많이 사용된다고 하네요!

  • 컴파일타임에 객체의 정확한 크기를 알지 못하지만 런타임에 객체의 정확한 크기를 알아야 할 때
    • => 리스트 같은 타입을 구현해야 할 때
  • 매우 큰 객체를 복사 없이 소유권만 옮기고 싶을 때
    • 스택에 있는 매우 큰 데이터를 복사하는 것보다는 heap에 생성된 데이터를 가리키는 포인터만 복사하는 것이 훨씬 빠름
  • 소유하고 싶은 객체가 어떤 타입인지 중요하지 않고 trait이 구현되었는지만 중요할 때

15.2. Treating Smart Pointers Like Regular References with the Deref trait

스마트 포인터를 일반 레퍼런스처럼 사용하고 싶을 때에는 Deref trait을 구현하면 됩니다.

  • Deref trait은 deref 메소드의 구현을 강제합니다.
  • dereference 연산의 동작 방식: *y => *(y.deref())

15.3. Running Code on Cleanup with Drop Trait

Drop trait은 drop 메소드의 구현을 강제하는데 drop 메소드는 객체가 스코프를 벗어날 때 자동으로 호출됩니다.

혹은 std::mem::drop 함수를 호출하는 것으로도 메모리를 일찍 해제할 수 있습니다.

15.4. Rc<T>, the Reference Counted Smart Pointer

Rc 스마트 포인터는 데이터의 reference counter를 관리하다가 reference counter가 0이 되면 메모리를 해제합니다.

 

하나의 데이터에 대한 소유권이 여러개 필요할 때 적절히 사용될 수 있습니다.

  • graph 데이터 구조에서 여러 엣지에 연결된 노드가 예시입니다.

15.5. RefCell<T> and the Interior Mutability Pattern

RefCell은 borrowing rule을 runtime에 강제할 수 있습니다.

  • borrowing rule이란?
    • 하나의 mutable reference 혹은 여러 개의 immutable reference만 가질 수 있음
    • reference는 항상 유효해야 함

borrowing rule을 runtime에 강제할 수 있다는 뜻은 개발자가 확신할 수 있는 상황에서는 컴파일러의 borrowing rule 확인을 끌 수 있다는 뜻입니다.

 

공식 문서에서는 Mock 객체를 통해서 RefCell을 유용하게 사용할 수 있는 예시를 보여줬습니다.

  • 원래 객체는 immutable한 필드를 가지고 있지만 Mock 객체는 테스트를 위해서 mutable한 필드를 가져야 할 때 RefCell을 사용하면 문제를 해소할 수 있음

Rc와 같이 사용하면 값을 수정할 수 있는 소유권을 여러개 가질 수 있게 됩니다.

 

15.6. Reference Cycles Can Leak Memory

Rc를 사용했는데 리스트의 head와 tail을 연결해버리는 경우처럼 cycle이 생기면  reference counter가 0으로 떨어지지 않아서 메모리 릭이 발생하게 됩니다.

 

이를 해소하는 방법으로는 Weak 스마트 포인터를 사용하는 것을 알려줍니다.

 

 

반응형