슬라이스(Slice)란?

  • 컬렉션 요소에 대한 참조자

Slice가 없을 때의 컬렉션 사용

fn main() {
    let mut s = String::from("hello world and yjk490");

    let x = first_word(&s);
    println!("{x}"); // 5 출력

    s.clear(); // 변수 str을 비워서 ""으로 변경
}

fn first_word(s :&String) -> usize {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if (item == b' ') {
            return i;
        }
    }

    s.len()
}
  • 공백으로 구분된 문자열을 매개변수로 받아 첫 번째 공백의 자리수를 반환하는 함수를 가정
  • 컴파일은 정상적으로 된다. 그러나 str.clear()를 호출한 후 x에 담긴 값은 더 이상 str의 첫 번째 공백 자리수를 의미하지 않는다.
  • 따라서 x에 담긴 5를 사용해서 str에서 첫 단어를 추출하는 데 사용할 경우 버그를 유발할 수 있음
  • 이처럼 컬렉션의 특정 요소를 추출할 때, 이후 컬렉션 원본이 변경되면 컴파일에는 문제가 없지만 추출한 요소는 의미가 없어진다.
  • 추출한 요소가 현재 컬렉션의 변경을 반영하고 있는지 계속 체크해야 하며, 추출한 요소는 데이터의 특정 상태에 의존하는 문제가 생긴다.

Slice의 사용

  • & 기호와 함께 참조하고자 하는 시작 인덱스와 끝 인덱스를 명시
    • let x = &y[0..3]
    • 0 부터 시작하면 시작 인덱스 생략 가능 `let x = &y[..3]
    • 마지막 인덱스까지 참조하면 끝 인덱스 생략 가능 let x = &y[5..]
  • 끝 인덱스에서 1을 뺀 인덱스까지 참조
  • 내부적으로 시작 위치, 길이를 데이터 구조에 저장하며 길이 값은 끝 인덱스에서 시작 인덱스를 빼서 계산
  • 원본 컬렉션이 수정되면 슬라이스도 영향을 받음
fn main() {
    let mut s = String::from("hello world and yjk490");

    let slice_1 = &s[0..5];
    let slice_2 = &s[6..11];
    println!("{slice_1}");    // hello 출력
    println!("{slice_2}");    // world 출력
}

Slice를 통해 컬렉션 사용

fn main() {
    let mut s = String::from("hello world and yjk490");

    let x = first_word_by_slice(&s);

    // 아래 코드 주석 해제 시, 컴파일 에러 발생
    // s.push_str("test"); 
    println!("{x}");
}

fn first_word_by_slice(s :&String) -> &str { // &str은 문자열 슬라이스 타입
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }

    &s[..]  // 공백이 없으면 전체 문자열 슬라이스 반환
}
  • x에는 문자열 슬라이스가 저장되어 있으므로 원본 문자열이 변경되면 x에도 반영된다.
  • s.push_str("test") 코드 사용 시 컴파일 에러 발생
    • s는 가변 참조자인데 push_str() 호출 이후 같은 스코프 내에서 불변 참조자x가 사용되기 때문
    • Rust에서는 불변 참조자가 있으면 가변 참조자를 생성할 수 없다.
    • 원본 문자열이 변경된 뒤 문자열 슬라이스가 사용되는 것을 문법적으로 방지한다.

'Rust' 카테고리의 다른 글

[Rust] 대여와 참조  (0) 2024.04.27
[Rust] &str vs String : 문자열을 표현하는 두 타입 비교  (0) 2024.04.25
[Rust] 소유권  (0) 2024.04.24
[Rust] 제어문 : 분기 처리와 반복  (0) 2024.04.16
[Rust] 함수  (0) 2024.04.15

+ Recent posts