참조는 근본적으로 메모리 상의 어떤 바이트들의 시작 위치를 가리키는 숫자일 뿐이며
유일한 용도는 특정 타입의 데이터가 어디에 존재하는지에 대한 개념을 나타내는 것이다.
일반 숫자와의 차이점은 Rust에서 참조가 가리키는 값보다 오래 살지 않도록 수명을 검증한다.
참조는 더 원시적인 자료형인 원시 포인터로 변환 가능
원시 포인터는 숫자와 마찬가지로 거의 제한없이 복사, 이동 가능
Rust는 원시 포인터가 가리키는 메모리 위치의 유효성을 보증하지 않는다.
원시 포인터는 숫자와 상호 변환이 가능.
원시 포인터는 안전하지 않은 코드의 데이터에 접근 할 수 있다.
let a = 42;
let memory_location = &a as *const i32 as usize;
println!("Data is here {}", memory_location);
참조(ex: &i32)를 통해 참조되는 데이터를 접근/변경하는 과정을 역참조라고 한다.
참조로 데이터를 접근/변경하는 데에는 두 가지 방법
let a: i32 = 42;
let ref_ref_ref_a: &&&i32 = &&&a;
let ref_a: &i32 = **ref_ref_ref_a;
let b: i32 = *ref_a;
println!("{}", b);
. 연산자는 참조의 필드와 메소드에 접근하는데 사용
let f = Foo { value: 42 };
let ref_ref_ref_f = &&&f;
println!("{}", ref_ref_ref_f.value);//자동으로 역참조
println!("{}", (***ref_ref_ref_f).value);
좀 헤깔리게 동작하는데, 참조 열을 자동으로 역참조 한다.
fn return_str() -> &'static str {
let test_str = String::from("Hey");
&test_str // error
}
fn main() {
let test_str = return_str();
println!("test_str");
}
참조 반환은 소유권을 넘기지 않는다. 함수 안에서 생성된 인스턴스를 참조로 반환하면 인스턴스 소유권이 반환되지 않고 그대로 함수의 소유이고 인스턴스는 함수가 종료할 경우 소멸되기에 에러가 발생한다.