슬라이스



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

let i = first_world(&s);

s.clear(); // 문자열 제거 (공백 문자열 "" 이 됨)

println!("{}", i);
}

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

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


위 코드에서, 변수 i 는 공백 문자의 인덱스, 6 을 가짐. 그런데 s.clear 가 호출되면서 원 문자열은 사라지고, 변수 i 의 값은 그 의미를 상실함: 인덱스 숫자 6은 여전히 남아있지만, 문자열이 사라졌기 때문에 존재 가치가 사라지는 셈. 관련된 데이터가 서로 독립적으로 존재하기 때문에 이런 현상이 발생함.


이를 방지하기 위해 슬라이스를 사용할 수 있음.


슬라이스는 다음과 같이 [시작위치..끝위치] 를 지정함으로써 생성됨.


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

let hello = &s[0..5]; // 인덱스 0 부터 5
let hello = &s[..5]; // 인덱스 0 부터 5

let world = &s[7..12]; // 인덱스 7 부터 12
let world = &s[7..]; // 인덱스 7 부터 12
let hello_world = &s[..len]; // 인덱스 0 부터 끝까지
let hello_world = &s[0..len]; // 인덱스 0 부터 끝까지
let hello_world = &s[..]; // 인덱스 0 부터 끝까지


슬라이스는 아래와 같은 효과를 가짐. (s 가 원본 변수, world 가 슬라이스) 지정된 범위의 시작을 가리키는 포인터를 가지며, 역시 원본 데이터와 같은 데이터를 가리킴.



아까의 함수 first_world 예제로 돌아가서, 슬라이스를 사용하면 world 는 원본 데이터를 가리키기 때문에 아까와 같은 현상은 발생하지 않음. 


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

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


이제 인티저 인덱스 값이 아닌, 슬라이스를 반환. 슬라이스의 타입은 &str 임. 이는 스트링 리터럴과 같은 타입임. (스트링 리터럴이 &str 인 이유는, 소스 코드에 입력된 값(리터럴)은 그대로 바이러니에 존재하고, 스트링 리터럴은 담고 있는 변수는 이 바이러니의 특정 위치(리터럴이 존재하는 위치)를 참조하는 것이기 때문. 그렇기에 스트링 리터럴은 태생적으로 참조이며, &str 이며, 임뮤터블임.)


여기서 아까처럼 원본 데이터에 변경되면?


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

let i = first_world(&s);

s.clear(); // 문자열 제거 (공백 문자열 "" 이 됨)

println!("{}", i);
}

위 코드는 컴파일 에러를 일으킴. 


레퍼런스 대여 규칙에, 한 데이터에 대한 임뮤터블 레퍼런스가 존재하면 이 데이터의 뮤터블 레퍼런스를 대여할 수 없도록 되어 있음. first_world 는 임뷰터블 변수 i 로 슬라이스를 반환하였고, 변수 i 는 원본 데이터를 가리키는(슬라이스는 원본 데이터를 가리키니까) 임뮤터블 변수가 됨. 그런데 문자열을 지워버리는 함수 clear 는 당연히 뮤터블 레퍼런스가 필요함. 여기서 충돌이 발생하여 컴파일 시점에 에러가 발생함.


러스트의 오너십과 슬라이스의 동작은 이런 방식으로 컴파일 타임에 레퍼런스의 혼재에 따른 안정성을 획득함.



'Rust' 카테고리의 다른 글

구조체(활용)  (0) 2018.02.20
구조체(기본)  (0) 2018.02.19
오너십(레퍼런스와 대여)  (0) 2018.02.15
오너십  (0) 2018.02.15
컨트롤 플로우(루프)  (0) 2018.02.15

+ Recent posts