Thinking Different




참조자 (References : &)

함수 또는 변수 개체에게 소유권을 넘기지는 않고 값은 사용할 수 있도록 해주는 기능입니다.

참조자의 경우 c++ 에서 포인터 사용에 따른 메모리 접근 보안성의 문제점을 해결하기 위해서 나온 기능입니다.

참조자의 경우 불변 참조자와 가변 참조자가 있습니다.

 

 

참조자의 규칙

참조자의 경우 항상 유효해야만 하며, 어떠한 경우이든 둘 중 하나만 가질 수 있습니다:
   - 하나의 가변 참조자
   - n개의 불변 참조자

 

 

일반적인 참조자 예제

fn main()
{
    // 참조자
    let a = 10;
    let b = &a;  // a를 참조하는 변수 b를 생성
}

 

함수에서 참조자 사용 예제

fn main()
{
    let s = String::from("Hello Rust!");
    
    // 문자열 길이를 반환하여 출력하며, 참조자로 넘겼으므로 s 출력도 에러없음
    println!("{}, {}", str_len(&s), s);
}

fn str_len(s: &String) -> usize
{
    s.len()
    // 일반적으로 소유권을 넘겨주었을때는 s가 소멸되므로 println! 구문에서 오류가 되지만
    // 참조자를 사용하여 넘겨받았으므로 이상 없이 출력된다.
}



// 결과
11, Hello Rust!

 

 

가변 참조자(mutable References)

 

가변 참조자의 경우 &mut 변수명 으로 생성할 수 있으며, 함수 매게변수도 변수명 : &mut 타입 으로 받아야 됩니다.

가변 참조자는 특정한 스코프 내에서는 한번에 딱 1개만 생성 가능하다는 제한이 있습니다.

 

아래와 같이 2번 사용하게 되면 에러가 발생됩니다.

let mut str = String::from("Hello Rust");

let s1 = &mut str;
let s2 = &mut str;  // 가변참조자는 1개만 생성가능하므로 에러

 

또한 불변 참조자를 사용하면서 동시에 가변 참조자를 생성할 수 없습니다.

let mut str = String::from("Hello Rust");

let s1 = &str;
let s2 = &str;
let s3 = &mut str;  // 에러 발생

 

 

함수 사용 가변 참조자 예제

fn main()
{
    // 가변 참조자
    let mut str = String::from("Hello");
    
    // 문자열 변경
    add_str(&mut str);

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

fn add_str(s: &mut String)
{
    s.push_str(" World!");
}



// 결과
Hello World!

 

 

 

댕글링 참조자(dangling References)

 

댕글링 포인터란 이미 할당되고 해제된 메모리 영역을 포인터가 계속 가리키고 있는 경우에 발생된다. 이를 댕글링 포인터라고 한다.

러스트에서는 이러한 댕글링 포인터(참조자)가 발생되지 않도록 컴파일러가 제어해준다.

 

간단히 댕글링 참조자 예시를 보며 이해하도록 하자

fn main()
{
    // 이미 해제된 영역을 얻어오려 했으므로 댕글링 참조자가 되버림
    let str = dangle();
}

fn dangle() -> &String
{
    let s = String::from("Hello Rust!");
    
    // 참조자로 넘겨주려고 하지만 } 스코프 끝을 만나면서 s가 소멸된다
    &s
}


// 결과 댕글참조자로 컴파일러에서 에러 처리
error[E0106]: missing lifetime specifier
 --> src/main.rs:7:16
  |
7 | fn dangle() -> &String
  |                ^ expected named lifetime parameter

 

이것을 댕글링 참조자가 되지 않게 하기 위해서는 그냥 소유권을 넘기도록 예제를 변경하면 된다.

fn dangle() -> String
{
    let s = String::from("Hello Rust!");
    
    // 소유권을 넘김
    s
}

'프로그래밍 언어 > Rust' 카테고리의 다른 글

[Rust] 10. 구조체(Struct)  (0) 2023.02.10
[Rust] 9. 슬라이스  (0) 2023.02.08
[Rust] 7. 소유권 그리고 스택과 힙  (1) 2023.02.02
[Rust] 6. 제어문과 반복문 (if, loop, for, while)  (0) 2023.01.26
[Rust] 5. 주석  (0) 2023.01.26