참조로 소유권 차용 (Rust)

11870 단어 Rust

참조에 의한 소유권 차용


  • 이번에는, 소유권을 받지 않고 값을 참조하는 방법에 대해 정리해 갑니다.
  • 참조는 & 연산자를 사용하는 것으로 할 수 있습니다.

  • 예:
    struct Foo {
        x: i32,
    }
    
    fn main() {
        let foo = Foo { x: 13 };
        let f = &foo;
        println!("{}", f.x);
        // ①:ここで変数fはドロップします。
        // ②:ここで変数fooはドロップします。
    }
    

    [실행 결과]
    ❯ cargo run   Compiling variables v0.1.0 (/Users/yoshitaka.koitabashi/Desktop/variables)    Finished dev [unoptimized + debuginfo] target(s) in 1.55s     Running `target/debug/variables`
    13
    
  • 다음은 또 다른 예입니다.
  • 여기에서는 값의 소유권을 받는 대신 인수로서 객체에 대한 참조를 취하는(s: &String)을 인수로 하고 있는 것을 알 수 있는 calculate_length 함수를 정의합니다.
  • 이 때, 오브젝트의 참조의 방법으로서는 아래와 같이 된다.


  • 또, 함수의 인수에 참조를 취하는 것을 차용이라고 합니다.

  • 예:
    fn main() {
        let char1 = String::from("hello world");
        let len = calculate_length(&char1);
    
        println!("length: '{}' is {}.", char1, len);
    }
    
    fn calculate_length(s: &String) -> usize {
        s.len()
    }
    

    [실행 결과]
    ❯ cargo run
       Compiling variables v0.1.0 (/Users/yoshitaka.koitabashi/Desktop/variables)
        Finished dev [unoptimized + debuginfo] target(s) in 0.31s
         Running `target/debug/variables`
    length: 'hello world' is 11.
    

    참조에 의한 소유권의 가변 차용


  • Rust에서 소유자는 가변 차용 중에 이동하거나 변경할 수 없습니다.
  • 아래의 예에서는, 함수의 인수에 참조를 사용해, 차용한 것에 대해서 변경을 걸고 있습니다.
  • 이 경우 실행 결과와 같이 오류가 발생합니다.

  • 예:
    fn main() {
        let s = String::from("hello");
    
        change(&s);
    }
    
    fn change(some_string: &String) {
        some_string.push_str(", world");
    }
    

    [실행 결과]
    ❯ cargo run
       Compiling variables v0.1.0 (/Users/yoshitaka.koitabashi/Desktop/variables)
    error[E0596]: cannot borrow `*some_string` as mutable, as it is behind a `&` reference
     --> src/main.rs:8:5
      |
    7 | fn change(some_string: &String) {
      |                        ------- help: consider changing this to be a mutable reference: `&mut String`
    8 |     some_string.push_str(", world");
      |     ^^^^^^^^^^^ `some_string` is a `&` reference, so the data it refers to cannot be borrowed as mutable
    
    error: aborting due to previous error
    
    For more information about this error, try `rustc --explain E0596`.
    error: could not compile `variables`
    
    To learn more, run the command again with --verbose.
    
  • 그래서, 참조에 의한 소유권의 가변에 차용하기 위해서 &mut 연산자를 사용합니다.
  • 단지 규칙이 있으며 데이터 충돌을 방지하기 위해 Rust는 동시에 두 변수에서 값을 변경할 수 없습니다.

  • 예:
    struct Foo {
        x: i32,
    }
    
    fn do_something(f: Foo) {
        println!("{}", f.x);
        // ここで引数fはドロップします。
    }
    
    fn main() {
        let mut foo = Foo { x: 13 };
        let f = &mut foo;
    
        f.x = 13;
        // ここで変数fはドロップします。=> つまり、変な借用もここでドロップします。
    
        println!("{}", foo.x);
    
        // 可変な借用はドロップされているため変更可能となります。
        foo.x = 7;
    
        // 変数fooの所有権を関数do_somethingに移動します。
        do_something(foo);
    }
    

    [실행 결과]
    ❯ cargo run
       Compiling variables v0.1.0 (/Users/yoshitaka.koitabashi/Desktop/variables)
        Finished dev [unoptimized + debuginfo] target(s) in 0.33s
         Running `target/debug/variables`
    13
    7
    

    참조 해제


  • &mut 참조는 * 연산자로 참조를 제거하여 소유자의 값을 설정할 수 있습니다.

  • 예:
    fn main() {
        let mut foo = 26;
        let f = &mut foo;
    
        // 参照を外し、所有者の値を取得します。
        let bar = *f;
    
        // 参照を外し、参照の所有者の値を設定します。
        *f = 13;      
        println!("{}", bar);
        println!("{}", foo);
    }
    

    [실행 결과]
    ❯ cargo run
       Compiling variables v0.1.0 (/Users/yoshitaka.koitabashi/Desktop/variables)
        Finished dev [unoptimized + debuginfo] target(s) in 0.23s
         Running `target/debug/variables`
    26
    13
    

    참조 참조



    예:
    struct Foo {
        x: i32,
    }
    
    fn do_something(a: &Foo) -> &i32 {
        return &a.x;
    }
    
    fn main() {
        let mut foo = Foo { x: 42 };
        let x = &mut foo.x;
    
        *x = 13;
        // 参照を外し、参照の所有者の値を設定します。
        // ここで変数xはドロップされます。
        // そのため、不変な参照が作成が可能になります。
        let y = do_something(&foo);
        println!("{}", y);
    }
    

    [실행 결과]
    ❯ cargo run
       Compiling variables v0.1.0 (/Users/yoshitaka.koitabashi/Desktop/variables)
        Finished dev [unoptimized + debuginfo] target(s) in 0.20s
         Running `target/debug/variables`
    13
    

    참고문헌


  • THE BOOK 4장
  • Tour of Rust
  • 좋은 웹페이지 즐겨찾기