REFERENCES / BORROWING

참조는 소유권을 넘기지 않고 잠시 빌려 쓰는 방법이다

&s1은 값을 가져가는 것이 아니라, 소유자인 s1을 가리키는 읽기 통로를 만든다. 그래서 함수 호출 뒤에도 원래 값은 그대로 사용할 수 있다.

소유권 이동 대신 주소를 빌려준다

함수는 길이만 읽으면 되므로 String 자체가 아니라 참조자를 받으면 충분하다.

Owner

s1이 String을 소유

s1: String
h e l l o
let s1 = String::from("hello");
Borrow

calculate_length가 &String을 받음

call
let len =
  calculate_length(&s1);

&s1은 소유권을 가져가지 않는다.

use after
println!("{}", s1);

대여가 끝나면 원래 소유자는 계속 사용할 수 있다.

읽기 대여와 쓰기 대여는 동시에 섞이지 않는다

여러 사람이 읽는 것은 괜찮지만, 쓰는 사람이 있으면 혼자만 접근해야 데이터 경합을 막을 수 있다.

허용

여러 불변 참조자

let r1 = &s;
let r2 = &s;
println!("{r1} {r2}");

모두 읽기만 하므로 값이 중간에 바뀔 걱정이 없다.

조건부 허용

하나의 가변 참조자

let r = &mut s;
r.push_str("!");

수정할 수 있지만 같은 값에 대한 다른 참조와 겹치면 안 된다.

차단

읽기와 쓰기 동시 접근

let r1 = &s;
let r2 = &mut s;

읽는 쪽은 값이 변하지 않는다고 믿기 때문에 컴파일러가 막는다.

참조의 유효 기간은 마지막 사용 지점까지다

참조가 더 이상 쓰이지 않으면 그 뒤에 가변 참조를 만들 수 있다.

1

읽기 참조 생성

let r1 = &s;
let r2 = &s;

둘 다 읽기만 하는 참조다.

2

마지막 사용

println!("{r1} {r2}");

이 지점 이후 r1, r2는 더 이상 쓰이지 않는다.

3

가변 참조 가능

let r3 = &mut s;

읽기 참조와 사용 구간이 겹치지 않으므로 허용된다.

dangling 방지

죽은 값은 가리킬 수 없음

fn dangle() -> &String { ... }

반환된 참조가 사라진 값을 가리키면 컴파일 오류가 난다.