[ RustπŸ¦€ ] Rust 의 μ†Œμœ κΆŒ

Rust 의 μ–Έμ–΄λ‘œμ„œμ˜ 보편적인 κΈ°λŠ₯을 μ•Œ 수 μžˆλ‹€.

이전 ν¬μŠ€νŠΈμ—μ„œ Rust 의 기본적인 속성듀을 μ•Œμ•„ λ³΄μ•˜λ‹€. 이번 ν¬μŠ€νŠΈμ—μ„œλŠ” Rust 의 핡심 κ°œλ…μ΄λΌκ³  ν•  수 μžˆλŠ” μ†Œμœ κΆŒ 에 λŒ€ν•΄ μ•Œμ•„λ³΄μž.

μ†Œμœ κΆŒμ΄ λ­”κ°€μš”? ( Ownership )

μš°λ¦¬λŠ” 이전에 μ‚¬μš©ν•˜λ˜ 언어듀을 μ“°λ©΄μ„œ, λ³€μˆ˜μ˜ μœ νš¨μ„±μ— λ”°λ₯Έ 였λ₯˜λ₯Ό 많이 κ²ͺμ–΄μ™”λ‹€.

Rust λŠ” μ΄λŸ¬ν•œ λ¬Έμ œλ“€μ„ ν•΄κ²°ν•˜κΈ° μœ„ν•΄ μ†Œμœ κΆŒ μ΄λΌλŠ” κ°œλ…μ„ λ„μž…ν–ˆλ‹€.

μ†Œμœ κΆŒμ΄λž€, λ³€μˆ˜κ°€ μ–΄λ–€ 값을 μ†Œμœ  ν•  수 μžˆλŠ” 것을 λ§ν•œλ‹€.
μ•žμ„œ, Rust 의 μ†Œμœ κΆŒμ— λŒ€ν•œ κ·œμΉ™μ„ μ•Œμ•„λ³΄μž.

  1. 러슀트의 각각의 값은 ν•΄λ‹Ήκ°’μ˜ μ˜€λ„ˆ(owner)라고 λΆˆλ¦¬μš°λŠ” λ³€μˆ˜λ₯Ό κ°–κ³  μžˆλ‹€.
  2. ν•œλ²ˆμ— λ”± ν•˜λ‚˜μ˜ μ˜€λ„ˆλ§Œ μ‘΄μž¬ν•  수 μžˆλ‹€.
  3. μ˜€λ„ˆκ°€ μŠ€μ½”ν”„ λ°–μœΌλ‘œ λ²—μ–΄λ‚˜λŠ” λ•Œ, 값은 버렀진닀(dropped).


Rust λŠ” μ΄λŸ¬ν•œ μ†Œμœ κΆŒ 을 톡해, JAVA 같은 λ³„λ„μ˜ GC도 두지 μ•ŠμœΌλ©΄μ„œ, C 처럼 memory leak 의 μœ„ν—˜λ„ μ—†λŠ” μ•ˆμ •μ„±μ„ κ΅¬ν˜„ν•΄ λƒˆλ‹€.

λ³€μˆ˜μ˜ μŠ€μ½”ν”„ ( Scope )

타 언어와 λ™μΌν•˜κ²Œ, Rust 의 λ³€μˆ˜λ„ μŠ€μ½”ν”„(Scope) λ₯Ό 가진닀. λ³€μˆ˜λŠ” ν•΄λ‹Ή μŠ€μ½”ν”„ λ‚΄μ—μ„œλ§Œ μ‚¬μš©ν•  수 있으며, μŠ€μ½”ν”„λ₯Ό λ²—μ–΄λ‚  μ‹œ μžλ™μœΌλ‘œ Drop λœλ‹€.

{
    let s = String::from("hello"); // sλŠ” μ—¬κΈ°μ„œλΆ€ν„° μœ νš¨ν•©λ‹ˆλ‹€
}                                  // 이 μŠ€μ½”ν”„λŠ” 끝났고, sλŠ” 더 이상 
                                   // μœ νš¨ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€

λ³€μˆ˜μ™€ κ°’μ˜ 관계 : 이동 ( Move )

λ¨Όμ € 일반적으둜 λ³€μˆ˜κ°„ 값을 λ³΅μ‚¬ν•˜λŠ” μ½”λ“œμ˜ 예제λ₯Ό 보자.

fn main () {
    let x: i32 = 10;
    let y: i32 = x;

    println!("x : {}, y : {}", x, y);
}

μœ„ μ½”λ“œλŠ” y 의 값을 x 에 λ³΅μ‚¬ν•˜λŠ” 것이고, 아무 문제 없이 λ™μž‘ν•œλ‹€.

그러면, μœ„μ™€ 같은 경우λ₯Ό String 에 μ μš©ν•΄ 보자.

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

    println!("x : {}, y : {}", x, y);
}

μ΄μ „μ˜ μ½”λ“œμ™€ μ°¨μ΄λŠ” int νƒ€μž…μ—μ„œ String 인 νƒ€μž…μœΌλ‘œ 바뀐 것 λΏμ΄λ―€λ‘œ, 이 μ½”λ“œλ„ μ •μƒμ μœΌλ‘œ λ™μž‘ν•˜μ•Ό ν•  것 κ°™μ§€λ§Œ,
μ‹€μ œλ‘œ μ»΄νŒŒμΌν•΄λ³΄λ©΄, μ•„λž˜μ™€ 같은 컴파일 였λ₯˜κ°€ λ°œμƒν•œλ‹€.

error[E0382]: borrow of moved value: `x`
 --> src/main.rs:6:32
  |
3 |     let x: String = String::from("hello, world!");
  |         - move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait
4 |     let y: String = x;
  |                     - value moved here
5 | 
6 |     println!("x : {}, y : {}", x, y);
  |                                ^ value borrowed here after move
  

μœ„ 였λ₯˜μ—μ„œ 두 μ€‘μš”ν•œ 문ꡬλ₯Ό λ³Ό 수 μžˆλŠ”λ°, μ²«μ§ΈλŠ” value moved here 이고, λ‘˜μ§ΈλŠ” value borrowed here after move 이닀.
두 문ꡬ가 λ°”λ‘œ Rust 의 μ†Œμœ κΆŒ λ•Œλ¬Έμ— λ°œμƒν•œ 였λ₯˜μΈλ°, 4번째 쀄 x = y μ—μ„œ β€œhello, world!” String 에 λŒ€ν•œ μ†Œμœ κΆŒμ΄ x μ—μ„œ y 둜 μ΄λ™ν–ˆ 버고,
κ·Έ 이후 6번째 μ€„μ—μ„œ x λŠ” String 에 λŒ€ν•œ μ†Œμœ κΆŒ 을 가지고 μžˆμ§€ μ•Šμ§€λ§Œ 좜λ ₯ν•˜λ € ν–ˆκΈ° λ•Œλ¬Έμ— λ°œμƒν•œ 였λ₯˜μ΄λ‹€.
이처럼 μ†Œμœ κΆŒμ„ 가진 λ³€μˆ˜λ₯Ό 1개둜 μœ μ§€ν•¨μœΌλ‘œμ¨, Dangling Pointer 의 참쑰에 λ”°λ₯Έ 였λ₯˜λ₯Ό 없앨 수 있고,
μ†Œμœ κΆŒμ„ 가진 λ³€μˆ˜κ°€ Scope 을 λ²—μ–΄λ‚  λ•Œ 값도 ν•¨κ»˜ Drop μ‹œν‚΄μœΌλ‘œμ¨ memory leak 도 방지할 수 μžˆλŠ” 것이닀. \ \

κ·Έλ ‡λ‹€λ©΄, 첫번째 κ²½μš°μ— 컴파일 였λ₯˜κ°€ λ‚˜μ§€ μ•Šμ•˜λ˜ μ΄μœ λŠ” λ¬΄μ—ˆμΌκΉŒ?
μ°¨μ΄λŠ” λ°”λ‘œ, μ²«λ²ˆμ§ΈλŠ” primitive ν˜•μ˜ λ³€μˆ˜λ₯Ό μ‚¬μš©ν–ˆκ³ , λ‘λ²ˆμ§ΈλŠ” reference ν˜•μ˜ λ³€μˆ˜λ₯Ό μ‚¬μš©ν–ˆλ‹€λŠ” 것이닀.

μ΄λŠ” λ‹€μŒ λ¬Έλ‹¨μ—μ„œ μ„€λͺ…ν•˜κ² λ‹€. \

λ³€μˆ˜μ™€ κ°’μ˜ 관계 : 볡사 ( Copy )

Rust μ—μ„œλ„ λ³€μˆ˜κ°„ 값을 λŒ€μž…ν•  λ•Œ, 항상 μ†Œμœ κΆŒμ˜ 이동이 μΌμ–΄λ‚˜λŠ” 것은 μ•„λ‹ˆλ‹€.
κ°’μ˜ μ†Œμœ κΆŒμ΄ μ΄λ™λ˜μ§€ μ•Šκ³ , κ°’ μžμ²΄κ°€ λ³΅μ‚¬λ˜λŠ” κ²½μš°κ°€ μžˆλŠ”λ°, μ΄λŠ” λ³€μˆ˜κ°€ STACK 에 λ“€μ–΄κ°ˆ 수 μžˆλŠ” ( 컴파일 νƒ€μž„μ— 크기λ₯Ό μ•Œ 수 μžˆλŠ” ) primitive ν•œ 값일 κ²½μš°μ΄λ‹€.

값이 λ³΅μ‚¬λ˜λŠ” νƒ€μž…μ€ μ•„λž˜μ™€ κ°™λ‹€.

λ˜ν•œ μžμ‹ μ΄ 직접 λ§Œλ“  ꡬ쑰체에λ₯Ό Copy 되게 ν•  수 도 μžˆλŠ”λ°, μ•„λž˜μ²˜λŸΌ Copy trait 을 κ΅¬ν˜„ν•˜λ©΄ λœλ‹€. ( μžμ„Έν•œ λ‚΄μš©μ€ λ‚˜μ€‘μ— 닀루겠닀. )

#[derive(Copy,Clone,Debug)]  // Copy trait ꡬ
#[derive(Debug)]
struct mystruct {
    x: i32,
    y: i32
}
impl mystruct {
    fn new(_x: i32, _y: i32) -> mystruct {
        mystruct{x: _x, y: _y}
    }
}
fn main () {
    let a = mystruct::new(1,1);
    let b = a;          // Copy Trait 을 κ΅¬ν˜„ν•¨μœΌλ‘œμ¨,
    print!("{:?}",a);   // 값을 μ΄λ™μ‹œμΌ°μ§€λ§Œ Copy λ˜μ–΄ 컴파일 였λ₯˜ λ°œμƒν•˜μ§€ x
}

References