Rust Slice Type에 대해

고승우·2023년 6월 5일
0
post-thumbnail

The Slice Type

slices는 collection의 연속된 일부를 참조할 수 있게 해준다. slice는 reference(참조)의 한 종류이므로 소유권을 갖지 않는다. 예시로 String에서 첫 번째 단어의 끝부분의 인덱스를 찾는 함수를 만들었다.

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()
}

String 요소 하나하나를 보면서 그 값이 공백인지 확인할 필요가 있기 때문에, Stringas_byte 메소드를 이용하여 바이트 배열로 변환한다. 다음으로 iter 메소드를 이요하여 바이트 배열의 반복자(iterator)를 생성한다. enumerate 메소드가 튜플을 반환하고 요소의 참조자를 갖기 위해서 &을 패턴 내에 사용했다.

String의 첫 번째 문자를 저장하고 있는데 해당 String이 삭제되는 상황을 가정해보자.

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

    let word = first_word(&s); // word will get the value 5

    s.clear(); // this empties the String, making it equal to ""
    // word still has the value 5 here, but there's no more string that
    // we could meaningfully use the value 5 with. word is now totally invalid!
}

s가 삭제되어도 word는 이후에 접근이 가능하다. 이런 상황이 error를 유발할 수 있다. rust에서는 string slice으로 해결할 수 있다.

String Slices

string sclice는 String 일부분에 대한 reference이다. 우리는 [starting_index..ending_index] 형태로 range를 특정한다. 다른 range와 마찬가지로 starting_index는 포함되고 ending_index는 포함되지 않는다. &str은 slice의 일종으로 볼 수 있으며, &str이 왜 immutable한 reference인지 추측할 수 있다.

    let s = String::from("hello world");

    let hello = &s[0..5];
    let world = &s[6..11];

let world = &s[6..11];의 경우, worlds의 6번째 바이트를 가리키고 길이값 5를 갖고 잇는 슬라이스가 될 것이다.

  • range를 표현할 때, index 0부터 시작하면 앞을 비워도 된다.
    let slice = &s[0..2];
    let slice = &s[..2];
  • 반대로 마지막 바이트를 포함할 때는 끝을 비워도 된다.
    let slice = &s[3..len];
    let slice = &s[3..];
  • 모든 String이 ASCII코드라는 가정 하에 이루어진다. 만약 multibyte character를 이용한다면, 이곳에서 정보를 얻을 수 있다.

이러한 정보를 바탕으로 코드를 수정해보자.

    let mut s = String::from("hello world");
    let word = first_word(&s);
    s.clear(); // error!
    println!("the first word is: {}", word);

    fn first_word(s: &String) -> &str {
        let bytes = s.as_bytes();
        for (i, &item) in bytes.iter().enumerate() {
            if item == b' ' {
                return &s[0..i];
            }
        }
        &s[..]
    }

이제는 String을 삭제하면 compile error 가 발생한다.

fn main() {
    let mut s = String::from("hello world");
    let word = first_word(&s);
    s.clear(); // error!
    println!("the first word is: {}", word);
}

rust는 String을 삭제하기 위해서 가변 참조자를 부른다 하지만, 우리는 이미 참조자를 갖고 있기 때문에, 컴파일 에러를 내며 프로그램이 종료된다.

Other Slices

slice에는 다양한 타입이 존재한다. Array타입 또한 마찬가지이다.

let a = [1, 2, 3, 4, 5];

let slice = &a[1..3];

assert_eq!(slice, &[2, 3]);
profile
٩( ᐛ )و 

0개의 댓글