RUST 구조체

Alpha, Orderly·2024년 6월 2일

RUST

목록 보기
3/11
post-thumbnail

구조체 (Struct)

Rust에서 구조체는 여러 개의 값을 하나의 의미 있는 묶음으로 정의할 수 있는 사용자 정의 타입입니다.

기본 구조체 정의 및 사용

struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}

fn main() {
    let mut user1 = User {
        active: true,
        username: String::from("someusername123"),
        email: String::from("someone@example.com"),
        sign_in_count: 1,
    };
    
    user1.email = String::from("anotheremail@example.com");
}
  • 구조체는 struct 키워드와 이름으로 정의합니다.
  • 인스턴스를 생성할 때는 키: 값 형태로 필드를 지정합니다.
  • 구조체의 필드 값은 . 표기법으로 접근하거나 수정할 수 있습니다.
  • 구조체 이름이 명확하므로 필드명 자동 완성이 가능합니다.

필드 초기화 축약법

fn build_user(email: String, username: String) -> User {
    User {
        active: true,
        username,   // username: username 과 동일
        email,      // email: email 과 동일
        sign_in_count: 1,
    }
}
  • 함수 매개변수 이름과 구조체 필드명이 같을 경우 축약 가능.

기존 인스턴스를 이용한 생성 (.. 문법)

let user2 = User {
    email: String::from("another@example.com"),
    ..user1
};
  • .. 연산자를 사용하면 기존 인스턴스의 나머지 필드를 복사합니다.
  • 단, 소유권 이동이 일어나면 원래 인스턴스는 더 이상 사용할 수 없습니다.

튜플 구조체

struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

fn main() {
    let black = Color(0, 0, 0);
    let origin = Point(0, 0, 0);
    
    println!("Black: {} {} {}", black.0, black.1, black.2);
}
  • 필드명이 없고 값의 순서만으로 구분합니다.
  • 서로 같은 구조라도 타입명이 다르면 별개의 타입입니다.
  • 필드 접근은 인덱스(.0, .1, ...)로 합니다.

유사 유닛 구조체 (필드 없는 구조체)

struct AlwaysEqual;

fn main() {
    let subject = AlwaysEqual;
}
  • 데이터를 저장하지 않지만 특정 트레잇을 구현할 때 유용합니다.

#[derive(...)] 와 디버깅

Rust에서는 트레잇을 자동으로 구현하기 위해 #[derive(...)] 어트리뷰트를 사용합니다.

#[derive(Debug, PartialEq)]
struct Clock {
    hour: i32,
    minute: i32,
}
  • Debug : {:?} 포맷으로 구조체를 출력할 수 있습니다.
  • PartialEq : == 연산자로 비교할 수 있게 만듭니다.

예시:

let c1 = Clock { hour: 10, minute: 30 };
let c2 = Clock { hour: 10, minute: 30 };

println!("{:?}", c1);        // Clock { hour: 10, minute: 30 }
println!("{}", c1 == c2);   // true

자주 사용되는 파생 트레잇:

  • Clone : .clone() 으로 깊은 복제 가능
  • Copy : 스택에 있는 값을 복사해 할당 가능 (주로 단순 타입)
  • Eq : 완전한 동등 비교 가능 (PartialEq의 보강)
  • Ord : 순서 비교 가능 (<, >, <=, >=)

dbg! 매크로

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let scale = 2;
    let rect1 = Rectangle {
        width: dbg!(30 * scale),
        height: 50,
    };

    dbg!(&rect1);
}
  • dbg!는 값을 출력하고 반환합니다.
  • 코드 실행 중 어떤 값이 들어가는지 확인할 때 유용합니다.

메서드

구조체와 관련된 동작은 impl 블록 안에서 메서드로 정의합니다.

struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

fn main() {
    let rect1 = Rectangle { width: 30, height: 50 };
    println!("Area: {}", rect1.area());
}
  • 첫 번째 매개변수는 항상 self이며, 인스턴스를 의미합니다.
  • &self : 불변 참조, &mut self : 가변 참조, self : 소유권 이동

연관 함수 (Associated Functions)

impl Rectangle {
    fn square(size: u32) -> Self {
        Self { width: size, height: size }
    }
}

fn main() {
    let sq = Rectangle::square(3);
}
  • self를 받지 않는 함수는 연관 함수라고 합니다.
  • 보통 생성자 역할로 자주 쓰이며 타입명::함수명() 형태로 호출합니다.

여러 개의 impl 블록

  • 하나의 구조체에 대해 여러 impl 블록을 정의할 수 있습니다.
  • 트레잇 구현과 메서드 구현을 분리하는 데 자주 활용됩니다.
profile
만능 컴덕후 겸 번지 팬

0개의 댓글