4.0 Ownership

์†Œ์œ ๊ถŒ์€ ๋Ÿฌ์ŠคํŠธ์˜ ๊ฐ€์žฅ ํŠน์ง•์ ์ธ ๊ฐœ๋…์ด๋‹ค, ๋Ÿฌ์ŠคํŠธ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ, ๋˜๋Š” ๋Ÿฌ์ŠคํŠธ๊ฐ€ ์™œ ๋‹ค๋ฅธ ์–ธ์–ด๋“ค๋ณด๋‹ค ์ฃผ๋ชฉ๋ฐ›๋Š”์ง€ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์žฅ์ด๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

4.1.1 What is Ownership?

Ownership์€ ๋Ÿฌ์ŠคํŠธ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ทœ์น™์ด๋‹ค.

  • ๋ชจ๋“  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

  • ๊ฐ€์žฅ ๋Œ€ํ‘œ์ ์ธ ๋‘ ๊ฐˆ๋ž˜๋Š” GC(Garbage Collection)์™€ ์ˆ˜๋™ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋กœ ๋ณผ ์ˆ˜์žˆ๋‹ค.

  • GC๋Š” ํ”„๋กœ๊ทธ๋žจ์ด ์‹คํ–‰๋˜๋Š”๋™์•ˆ, ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฐพ์•„๋‚ด๊ณ  ํ•ด์ฒดํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

  • ์ˆ˜๋™ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋Š” ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ง์ ‘ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

  • ๋‹น์—ฐํžˆ GC๊ฐ€ ํŽธ๋ฆฌํ•˜๊ณ  ์•ˆ์ „ํ•˜์ง€๋งŒ, ์„ฑ๋Šฅ์ด ๋–จ์–ด์ง„๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค.

  • ๋Ÿฌ์ŠคํŠธ๋Š” ์„ธ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์ธ Ownership์„ ์‚ฌ์šฉํ•œ๋‹ค.

  • ๊ฐœ์ธ์ ์œผ๋กœ Ownership์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ํฌ์ธํŠธ๋Š” ‘๊ทœ์น™’์ด๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

  • ์†Œ์œ ๊ถŒ์ด ์ ์šฉ๋˜๋Š” ๊ทœ์น™์„ ์š”์•ฝํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

    • ๊ฐ๊ฐ์˜ ๊ฐ’์€ ์†Œ์œ ์ž(owner)๊ฐ€ ์žˆ๋‹ค.

    • ํ•œ๋ฒˆ์— ํ•˜๋‚˜์˜ ์†Œ์œ ์ž๋งŒ ์กด์žฌํ•  ์ˆ˜ ์žˆ๋‹ค.

    • ์†Œ์œ ์ž๊ฐ€ ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—์–ด๋‚˜๋ฉด, ๊ฐ’์€ ํ•ด์ œ๋œ๋‹ค.

  • ์‚ฌ์‹ค ์™„์ „ํžˆ ์ƒˆ๋กœ์šด ๋ฐฉ์‹์€ ์•„๋‹ˆ๋‹ค. C++์˜ RAII(Resource Acquisition Is Initialization)์™€ ๋น„์Šทํ•œ ๊ฐœ๋…์ด๋‹ค.

  • RAII๋Š” ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ, ์ž์›์„ ํ• ๋‹นํ•˜๊ณ , ์†Œ๋ฉธ๋  ๋•Œ ์ž์›์„ ํ•ด์ œํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

    • ๊ฐ์ฒด์˜ ์ƒ์„ฑ๊ณผ ์†Œ๋ฉธ์„ ์ž์›์˜ ํ• ๋‹น๊ณผ ํ•ด์ œ๋กœ ์—ฐ๊ฒฐ์ง“๋Š”๋‹ค.
  • ์ฐธ์กฐ๊ฐ€ ์—†์œผ๋ฉด(์Šค์ฝ”ํ”„๋ฅผ ๋‚˜๊ฐ€๋ฉด) ์ž๋™์œผ๋กœ ํ•ด์ œ๋œ๋‹ค๋Š” ์ ์—์„œ๋Š” GC์™€ ๋น„์Šทํ•˜๋‹ค.

    • GC๋ฅผ ์•„์ฃผ ๋ฌด์‹ํ•˜๊ฒŒ ์š”์•ฝํ•˜๋ฉด ์ฐธ์กฐ๊ฐ€ ์—†์–ด์ง„ ๋งค๋ชจ๋ฆฌ๋ฅผ ์ฒดํฌํ•˜๊ณ  ํšŒ์ˆ˜ํ•œ๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Rust๋Š”’๊ทœ์น™’์— ๊ธฐ๋ฐ˜ํ•œ ์†Œ์œ ๊ถŒ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค, ๋ฐ˜๋Œ€๋กœ ์ƒ๊ฐํ•˜๋ฉด, ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋‚ญ๋น„ํ•˜๊ฑฐ๋‚˜ ์œ„ํ—˜์— ๋น ๋œจ๋ฆฌ์ง€ ์•Š๋Š” ‘๊ทœ์น™์„’ ๊ตฌํ˜„ํ•œ ๊ฒƒ์— ๋” ํฐ ์˜์˜๊ฐ€ ์žˆ๋‹ค.

  • ๊ทธ์— ๋Œ€ํ•œ ๋Œ“๊ฐ€๋กœ Rust๋Š” ์ปดํŒŒ์ผํƒ€์ž„์— ๋ฉ”๋ชจ๋ฆฌ ์•ˆ์ •์„ฑ์„ ๊ฒ€์ฆ ํ•  ์ˆ˜ ์žˆ๊ณ , GC์™€ ๊ฐ™์ด ๋Ÿฐํƒ€์ž„์— ์ถ”๊ฐ€์ ์ธ ๋น„์šฉ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

  • ๊ฒฐ๋ก ์ ์œผ๋กœ ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” Rust์˜ Ownership์ด๋ผ๋Š” ๊ทœ์น™์„ ๋”ฐ๋ฅด๋ฉฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•˜๋Š” ๊ฒƒ์€ ์–ด๋ ต์ง€๋งŒ, ๊ทธ ๋Œ“๊ฐ€๋กœ ์•ˆ์ „ํ•˜๋ฉด์„œ๋„ ๋น ๋ฅธ ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

4.1.2 Stack and Heap

Stack๊ณผ Heap์€ ์šฐ๋ฆฌ์˜ ์ฝ”๋“œ๊ฐ€ ๋Ÿฐํƒ€์ž„์— ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”๋ชจ๋ฆฌ์ด๋‹ค. ์Šคํƒ์€ ์ž๋ฃŒ๊ตฌ์กฐ ์Šคํƒ์˜ ๊ฐœ๋…์„ ๋”ฐ๋ฅธ๋‹ค. LIFO๋Š” ๊ตณ์ด ์„ค๋ช… ์•ˆํ•ด๋„ ๊ดœ์ฐฎ์ง€๋งŒ, ํŠน์ •ํ•œ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์— ์ผ๋ ฌ๋กœ ๋Š˜์–ด์„œ ์žˆ๋Š” ์„ ํ˜• ์ž๋ฃŒ๊ตฌ์กฐ์ž„์€ ์ธ์ง€ํ•ด์•ผ ํ•œ๋‹ค. ์™œ๋ƒ๋ฉด ํž™์€ ์Šคํƒ๊ณผ ๋‹ค๋ฅด๊ฒŒ ๋ฉ”๋ชจ๋ฆฌ์˜ ์–ด๋Š ๊ณณ์—๋“  ํ• ๋‹นํ•˜๊ณ , ์ฒซ์นธ์˜ ํฌ์ธํ„ฐ๋ฅผ ๋ฐ˜ํ™˜๋ฐ›๊ธฐ ๋•Œ๋ฌธ์ธ๋‹ค. ๋ณดํ†ต ์Šคํƒ์€ ๋น ๋ฅด๊ณ , ํž™์€ ๋Š๋ฆฌ๋‹ค๊ณ  ์•Œ๋ ค์ ธ ์žˆ๋‹ค. ๊ทธ ์ด์œ ๋Š” ์Šคํƒ์€ LIFO๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ , ํž™์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์ฐพ๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€์ ์ธ ์ž‘์—…์ด ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์‹ค์ œ๋กœ๋Š” ์ฃผ๋กœ ํ˜ผ์šฉํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์Šคํƒ์— ํž™์˜ ํฌ์ธํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ , ์‹ค์ œ ์ฐธ์กฐ๊ฐ€ ํ•„์š”ํ•  ๋•Œ ํž™์„ ์ฐธ์กฐํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

  • ์ด ๋ ˆํผ๋Ÿฐ์Šค๊ฐ€ ์˜๋ฏธ์žˆ๋Š” ์ด์œ ๋ฅผ ์ž˜ ์ƒ๊ฐํ•ด ๋ด์•ผ ํ•œ๋‹ค.

  • Rust๋Š” Stack๊ณผ Heap์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.

  • ์˜ˆ๋ฅผ๋“ค์–ด ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ ๋  ๋•Œ ๋งˆ๋‹ค, ํ•จ์ˆ˜์˜ ์ง€์—ญ๋ณ€์ˆ˜์™€ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์Šคํƒ์— ์ €์žฅ๋œ๋‹ค(ํž™ ๋ฐ์ดํ„ฐ ํฌํ•จ). ๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ด ๋๋‚˜๋ฉด ์Šคํƒ์—์„œ ์ œ๊ฑฐ๋œ๋‹ค.

  • ๊ฒฐ๋ก ์ ์œผ๋กœ ์šฐ๋ฆฌ๊ฐ€ ๊ด€๋ฆฌํ•ด์•ผํ•˜๋Š” ๋ฐ์ดํ„ฐ๋Š” ์‚ฌ์‹ค์ƒ ํž™์— ํ• ๋‹น๋œ ๋ฐ์ดํ„ฐ์ด๋‹ค.

  • Stack์€ ์Šค์ฝ”ํ”„ ๋˜๋Š” ์‚ฌ์šฉ ์‹œ์ ์— ๋”ฐ๋ผ ์ž๋™์œผ๋กœ ๊ด€๋ฆฌ๋˜์ง€๋งŒ, ํž™์€ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ง์ ‘ ๊ด€๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.

  • ์ฑ…์—์„œ๋Š” Stack๊ณผ Heap์„ ์ƒ๊ฐํ•˜๋ฉด์„œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํ•ด์•ผ ํ•  ํ•„์š”๋Š” ์—†์ง€๋งŒ, Ownership ์‹œ์Šคํ…œ์ด ๋ญ˜ ์–ด๋–ป๊ฒŒ ํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ์™œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š”์ง€ ์ดํ•ดํ•˜๋Š”๋ฐ ๋„์›€์ด ๋œ๋‹ค๊ณ  ํ•œ๋‹ค.

4.1.3 Ownership Rules

๋‹ค์‹œ Ownership์˜ ๊ทœ์น™์„ ์‚ดํŽด๋ณด๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ๊ฐ๊ฐ์˜ ๊ฐ’์€ ์†Œ์œ ์ž(owner)๊ฐ€ ์žˆ๋‹ค.
  • ํ•œ๋ฒˆ์— ํ•˜๋‚˜์˜ ์†Œ์œ ์ž๋งŒ ์กด์žฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์†Œ์œ ์ž๊ฐ€ ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—์–ด๋‚˜๋ฉด, ๊ฐ’์€ ํ•ด์ œ๋œ๋‹ค.

์ด๋ถ€๋ถ„์„ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋Ÿฌ์ŠคํŠธ์˜ ๋ณ€์ˆ˜ ๋ฐ”์ธ๋”ฉ๋ฐฉ์‹, ์Šค์ฝ”ํ”„๋ฅผ ์ดํ•ดํ•ด์•ผ ํ•œ๋‹ค.

4.1.4 Variable Scope

** ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด ์—์„œ**

fn main() { // s is not valid here, it's not yet declared
    let s = "hello"; // s is valid from this point forward
} // this scope is now over, and s is no longer valid
  • ์œ„์˜ ์ฝ”๋“œ์— ๊ฐ€์žฅ ์ค‘์š”ํ•œ ํฌ์ธํŠธ
  • ๋ณ€์ˆ˜ s๋Š” ์„ ์–ธ๋œ ๋ธ”๋ก ๋‚ด์—์„œ๋งŒ ์œ ํšจํ•˜๋‹ค.
  • ๋ธ”๋ก์ด ๋๋‚˜๋ฉด ๋ณ€์ˆ˜ s๋Š” ์†Œ๋ฉธ๋œ๋‹ค.
  • ์•„์ง๊นŒ์ง€ ๋‹ค๋ฅธ ์–ธ์–ด์™€ ํฌ๊ฒŒ ๋‹ค๋ฅด์ง€ ์•Š๋‹ค.

4.1.5 The String Type

String ํƒ€์ž…์—์„œ

fn main() {
    let s = String::from("hello");
    // do stuff with s
} // this scope is now over, and s is no longer valid
  • String ํƒ€์ž…๋„ ๋ณ„๋ฐ˜ ๋‹ค๋ฅด์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™์€๋ฐ..?

4.1.6 Memory and Allocation

  • ๋ฌธ์ž ๋ฆฌํ„ฐ๋Ÿด์˜ ๊ฒฝ์šฐ, ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ปจํ…์ธ ๋ฅผ ์•Œ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ํ•ด๋‹น ์ปจํ…์ธ ๊ฐ€ ํ•˜๋“œ์ฝ”๋”ฉ๋˜์–ด ๋ฐ”์ด๋„ˆ๋ฆฌ์— ํฌํ•จ๋œ๋‹ค. ๊ทธ๋ž˜์„œ ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์ด์ง€๋งŒ, ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ๋ฐ˜๋ฉด String ํƒ€์ž…์€ ์ปดํŒŒ์ผ ํƒ€์ž„์— ํฌ๊ธฐ๋ฅผ ์•Œ ์ˆ˜ ์—†๊ณ , ๋Ÿฐํƒ€์ž„์— ํฌ๊ธฐ๊ฐ€ ๊ฒฐ์ •๋˜์–ด ํ• ๋‹น๋  ๊ณต๊ฐ„์„ ์ฐพ์•„ ํž™์— ์ €์žฅ๋˜์–ด์•ผ ํ•œ๋‹ค.

์ด ์‹œ์ ์— ๊ฐ€์žฅ ์ค‘์š”ํ•œ ํฌ์ธํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ๋Ÿฐํƒ€์ž„์— ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์„ ์š”์ฒญํ•ด์„œ ํ• ๋‹นํ•ด์•ผํ•œ๋‹ค.

  • ๊ทธ๋กœ์ธํ•ด ์ด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•ดํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•˜๋‹ค.

  • ์ฒซ ๋ฒˆ์งธ๋Š” String::from ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์ด๋ฃจ์–ด์กŒ๋‹ค (์‰ฝ๋‹ค ์‰ฌ์›Œ).

  • ๊ทธ๋Ÿฐ๋ฐ ๋‘ ๋ฒˆ์งธ๋Š” ํ”„๋กœ๊ทธ๋ž˜๋จธ๋“ค์˜ ์•„์ฃผ ์˜ค๋ž˜๋œ ๊ณ ๋ฏผ์ค‘์— ํ•˜๋‚˜์ด๋‹ค. (GC๊ฐ€ ์—†๋Š” ์–ธ์–ด์—์„œ๋Š”)

    • ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•˜๊ณ  ํ•ด์ œํ•˜๋Š” ๊ฒƒ์€ ํ”„๋กœ๊ทธ๋ž˜๋จธ์˜ ๋ชซ์ด๋‹ค.
    • ๊ทผ๋ฐ ๊ทธ๊ฒŒ ์ž˜ ๋˜๊ฒ ๋ƒ๊ณ , ์‚ฌ๋žŒ์€ ์‹ค์ˆ˜๋ฅผ ํ•˜๊ธฐ ๋งˆ๋ จ์ธ๋ฐ…
    • ์ผ๋‹จ ํ•ด์ œ๋ฅผ ์•ˆํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•ด์„œ ํ”„๋กœ๊ทธ๋žจ์ด ๋Š๋ ค์ง€๊ณ , ๋” ์‹ฌํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ์ด ์ฃฝ์„ ์ˆ˜ ์žˆ๋‹ค.
    • ํ•ด์ œ๋ฅผ ๋‘๋ฒˆํ•˜๋ฉด, ํ”„๋กœ๊ทธ๋žจ์ด ์ฃฝ์„ ์ˆ˜ ์žˆ๋‹ค.
    • ํ•ด์ œ๋ฅผ ๋„ˆ๋ฌด ์ผ์ฐํ•˜๋ฉด, ํ”„๋กœ๊ทธ๋žจ์ด ์ฃฝ์„ ์ˆ˜ ์žˆ๋‹ค.
    • ๊ฒฐ๋ก ์ ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋Š” ์–ด๋ ต๋‹ค.
  • Rust๋Š” Ownership ๊ทœ์น™์„ ํ†ตํ•ด ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ๋‹ค.

fn main() {
    let s = String::from("hello");
    // do stuff with s
} // this scope is now over, and s is no longer valid
  • ์œ„์˜ ์ฝ”๋“œ์—์„œ s๋Š” ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—์–ด๋‚˜๋ฉด ํ•ด์ œ๋œ๋‹ค. (์‰ฝ๊ณ  ํŽธ๋ฆฌํ•˜๊ณ  ์•ˆ์ „ํ•ด๋ณด์ด์ง€!, ์•ˆ์ „ํ•œ๊ฑด ๋งž๋Š”๋ฐ ์‰ฝ๊ณ  ํŽธํ• ๊นŒ?)

  • ๋ฌดํŠผ ์ด๊ฒƒ์ด Ownership์˜ ๊ทœ์น™์ด๋‹ค.

  • ์ฐธ๊ณ ๋กœ ์‹ค์ œ ๊ตฌํ˜„์€ drop์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์ด๋ฃจ์–ด์ง„๋‹ค.

  • ์Šค์ฝ”ํ”„์˜ ๊ธฐ์ค€์ด ๋˜๋Š” ๋‹ซํžŒ ์ค‘๊ด„ํ˜ธ๊ฐ€ ์‹คํ–‰๋˜๋ฉด, ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” drop ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜์–ด ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•ด์ œ๋œ๋‹ค.

4.1.7 Ways Variables and Data Interact : Move

  let x = 5;
  let y = x;
  • ์—ฌ๊ธฐ์„œ๋Š” x์˜ ๊ฐ’์„ ๋ณต์‚ฌํ•ด์„œ y์— ๋„ฃ๊ณ  ์‹ค์ œ๋กœ x์™€ y์ธ 5๋Š” ์Šคํƒ์— ๊ฐ๊ฐ ํ‘ธ์‹œ๋œ๋‹ค.
  let s1 = String::from("hello");
  let s2 = s1;
  • ์—ฌ๊ธฐ๋Š” ๋‹ค๋ฅด๋‹ค! String์˜ ๋ฐ์ดํ„ฐ๋Š” ์„ธ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋‰˜์–ด์ ธ ์žˆ๋‹ค (ํฌ์ธํ„ฐ, ๊ธธ์ด, ์šฉ๋Ÿ‰)

    • ํฌ์ธํ„ฐ๋Š” ํž™์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ฃผ์†Œ
    • ๊ธธ์ด๋Š” ๋ฐ์ดํ„ฐ์˜ ๊ธธ์ด
    • ์šฉ๋Ÿ‰์€ ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ์˜ ํฌ๊ธฐ
  • ์ผ๋‹จ ์ด ๋ฐ์ดํ„ฐ (์ฐธ์กฐ์™€ ๋ญ ๋Œ€์ถฉ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ)๋Š” ์Šคํƒ์— ์ €์žฅ๋œ๋‹ค.

image ์ถœ์ฒ˜ : The Rust Programming Language

  • ๊ทธ๋ฆฌ๊ณ  s1์„ s2์— ํ• ๋‹นํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?

  • ๊ฒฐ๋ก ์€ s1์˜ ๋ฐ์ดํ„ฐ์ค‘ ์Šคํƒ์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋Š” s2๋กœ ๋ณต์‚ฌ๋˜๊ณ , ํž™์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋Š” ๋ณต์‚ฌ๋˜์ง€ ์•Š๋Š”๋‹ค.

  • ๊ทธ๋Ÿฐ๋ฐ ๋ฌธ์ œ๋Š” ์—ฌ๊ธฐ์„œ ๋ฐœ์ƒํ•œ๋‹ค. s1๊ณผ s2๊ฐ€ ๋ชจ๋‘ ํž™์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ์œผ๋ฉด, ๋‘ ๋ณ€์ˆ˜๊ฐ€ ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—์–ด๋‚˜๋ฉด ๋‘ ๋ณ€์ˆ˜๊ฐ€ ๋™์‹œ์— ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•˜๋ ค๊ณ  ํ•  ๊ฒƒ์ด๋‹ค.

  • ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋‘๋ฒˆ ํ•ด์ œํ•ด…? “์ฃฝ์„๊ฒŒ”

  • ๊ฐ€ ์•„๋‹ˆ๊ณ  Rust๋Š” ์ด๋Ÿฐ ์ƒํ™ฉ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์žฅ์น˜๋ฅผ ๋งˆ๋ จํ•ด๋’€๋‹ค.

  • ๋‚ด์šฉ์„ ๋จผ์ € ๋ณด๋ฉด

  • let s2 = s1 ์ฝ”๋“œ ์ดํ›„์˜ ์‹œ์ ์—, s1์„ ๋”์ด์ƒ ์œ ํšจํ•˜์ง€ ์•Š๋‹ค๊ณ  ๊ฐ„์ฃผํ•œ๋‹ค.

  let s1 = String::from("hello");
  let s2 = s1;
  println!("{}, world!", s1);
$ cargo run
   Compiling ownership v0.1.0 (file:///projects/ownership)
error[E0382]: borrow of moved value: `s1`
 --> src/main.rs:5:28
  |
2 |     let s1 = String::from("hello");
  |         -- move occurs because `s1` has type `String`, which does not implement the `Copy` trait
3 |     let s2 = s1;
  |              -- value moved here
4 |
5 |     println!("{}, world!", s1);
  |                            ^^ value borrowed here after move
  |
  = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider cloning the value if the performance cost is acceptable
  |
3 |     let s2 = s1.clone();
  |                ++++++++

For more information about this error, try `rustc --explain E0382`.
error: could not compile `ownership` due to previous error
  • ์‹ค์ œ๋กœ ์ด๋Ÿฐ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

  • ์–•์€ ๋ณต์‚ฌ ๋‚˜๋„ ์•Œ์•„ ๋ผ๊ณ  ์ž…์ด ๊ทผ์งˆ๊ทผ์งˆํ•˜์…จ๋˜๋ถ„๋“ค์€ ๊ณ ๋ คํ•ด์•ผ ํ•  ๊ฒŒ ํ•˜๋‚˜ ๋” ๋Š˜์€ ์ƒ˜์ด๋‹ค.

  • Rust๋Š” ์–•์€ ๋ณต์‚ฌ๋ฅผ ํ•˜์ง€ ์•Š๊ณ , move๋ผ๋Š” ๊ฐœ๋…์„ ์‚ฌ์šฉํ•œ๋‹ค.

image ์ถœ์ฒ˜ : The Rust Programming Language

  • ๊ฒฐ๋ก ์ ์œผ๋กœ ์Šค์ฝ”ํ”„๋ฅผ ๋‚˜๊ฐˆ๋•Œ๋งˆ๋‹ค ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œํ•˜๋ฉด ๋˜๋Š”๋ฐ ์™œ ๊ทธ๋ ‡๊ฒŒ ์•ˆํ–ˆ์ง€? ์™€ ๊ฐ™์€ ์ƒ๊ฐ์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์œ ๊ฐ€ ์žˆ์—ˆ๊ณ (์ค‘๋ณต ํ•ด์ œ) ๋Ÿฌ์ŠคํŠธ๋Š” ์ด๋Ÿฌํ•œ ๋ถ€๋ถ„๋“ค์— ๋Œ€ํ•œ ๊ทœ์น™์„ ์ง€์ •ํ•˜๋ฉฐ ํ•ด๊ฒฐํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

  • ์ฐธ๊ณ ๋กœ ๊นŠ์€ ๋ณต์‚ฌ๋ฅผ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด clone ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

  let s1 = String::from("hello");
  let s2 = s1.clone();
  println!("{}, world!", s1);
  • ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด s1๊ณผ s2๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ๋œ๋‹ค.

4.1.8 Copy Trait

  • ์•ž์—์„œ ๋ถ„๋ฅ˜ํ•œ Stack only ํƒ€์ž…๋“ค์€ ๊ตณ์ด move๋ฅผ ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

  • ์ด๋Ÿฐ ํƒ€์ž…๋“ค์€ Copy ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋‹ค.

  • Copy ํŠธ๋ ˆ์ดํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์ง•์„ ๊ฐ€์ง„๋‹ค.

    • ์Šคํƒ์— ์ €์žฅ๋˜๋Š” ํƒ€์ž…๋“ค์€ Copy ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋‹ค.

    • Copy ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋Š” ํƒ€์ž…๋“ค์€ move ๋Œ€์‹  ๋ณต์‚ฌ๊ฐ€ ์ด๋ฃจ์–ด์ง„๋‹ค.

    • Copy ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋Š” ํƒ€์ž…๋“ค์€ ์Šค์ฝ”ํ”„๋ฅผ ๋ฒ—์–ด๋‚˜๋„ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•ด์ œ๋˜์ง€ ์•Š๋Š”๋‹ค.

  • Copy ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋Š” ํƒ€์ž…๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

    - i32
    
    - bool
    
    - f64
    
    - char
    
    - Tuple (๋‹จ, ๋ชจ๋“  ์š”์†Œ๊ฐ€ Copy ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค.)
    
  • ์ด์™ธ์—๋Š” drop trait๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ์–ด Copy ํŠธ๋ ˆ์ดํŠธ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์—†๋‹ค.

4.1.9 Ownership and Functions

  • ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๊ฐ’์„ ๋„˜๊ธฐ๋Š” ๊ฒƒ์€ ๋ณ€์ˆ˜๋ฅผ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ๊ณผ ์˜๋ฏธ๋ก ์ ์œผ๋กœ ๋น„์Šทํ•˜๋‹ค.

  • ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๊ฐ’์„ ๋„˜๊ธฐ๋ฉด, ํ•ด๋‹น ๊ฐ’์€ ํ•จ์ˆ˜์˜ ์Šค์ฝ”ํ”„๋กœ ์ด๋™ํ•œ๋‹ค.

fn main() {
    let s = String::from("hello");  // s comes into scope

    takes_ownership(s);             // s's value moves into the function...
                                    // ... and so is no longer valid here

    let x = 5;                      // x comes into scope

    makes_copy(x);                  // x would move into the function,
                                    // but i32 is Copy, so it's okay to still
                                    // use x afterward

} // Here, x goes out of scope, then s. But because s's value was moved, nothing
  // special happens.

fn takes_ownership(some_string: String) { // some_string comes into scope
    println!("{}", some_string);
} // Here, some_string goes out of scope and `drop` is called. The backing
  // memory is freed.

fn makes_copy(some_integer: i32) { // some_integer comes into scope
    println!("{}", some_integer);
} // Here, some_integer goes out of scope. Nothing special happens.
  • ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜๊ฐ’ ์—ญ์‹œ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ move๊ฐ€ ์ด๋ฃจ์–ด์ง„๋‹ค.
fn main() {
    let s1 = gives_ownership();         // gives_ownership moves its return
                                        // value into s1

    let s2 = String::from("hello");     // s2 comes into scope

    let s3 = takes_and_gives_back(s2);  // s2 is moved into
                                        // takes_and_gives_back, which also
                                        // moves its return value into s3
} // Here, s3 goes out of scope and is dropped. s2 was moved, so nothing
  // happens. s1 goes out of scope and is dropped.

fn gives_ownership() -> String {             // gives_ownership will move its
                                             // return value into the function
                                             // that calls it

    let some_string = String::from("yours"); // some_string comes into scope

    some_string                              // some_string is returned and
                                             // moves out to the calling
                                             // function
}

// This function takes a String and returns one
fn takes_and_gives_back(a_string: String) -> String { // a_string comes into
                                                      // scope

    a_string  // a_string is returned and moves out to the calling function
}
  • ๋‚ฉ๋“์ด ์•ˆ๊ฐ€๋Š” ์˜ˆ์ œ๋Š” ์—†๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

  • ๋‹ค๋งŒ ๋ชจ๋“  ํ•จ์ˆ˜๊ฐ€ ์†Œ์œ ๊ถŒ์„ ๊ฐ€์ ธ๊ฐ”๋‹ค๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š”๊ฒƒ์€ ์ง€๋ฃจํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋Ÿฌ์ŠคํŠธ๋Š” ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

4.2 References and Borrowing

fn main() {
    let s1 = String::from("hello");

    let len = calculate_length(&s1);

    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize { // s is a reference to a String
    s.len()
}
  • ๋Ÿฌ์ŠคํŠธ์—์„œ ์ฐธ์กฐ๋Š” ๋ณ€์ˆ˜๋ฅผ ๋นŒ๋ ค์˜ค๋Š” ๊ฒƒ์ด๋‹ค.

Rust Reference

  • ์ฐธ๊ณ ๋กœ reference์˜ ๋ฐ˜๋Œ€๋Š” dereference์ด๋ฉฐ * ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

  • ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์†Œ์œ ๊ถŒ์„ ๋„˜๊ธฐ์ง€ ์•Š์œผ๋ฏ€๋กœ, drop ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š๋Š”๋‹ค.

  • ์ฐธ์กฐ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ immutableํ•˜๋‹ค.

fn main() {
    let s = String::from("hello");

    change(&s);
}

fn change(some_string: &String) {
    some_string.push_str(", world");
}
  • ์œ„์˜ ์ฝ”๋“œ๋Š” ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
$ cargo run
   Compiling ownership v0.1.0 (file:///projects/ownership)
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

For more information about this error, try `rustc --explain E0596`.
error: could not compile `ownership` due to previous error
  • ์ฐธ์กฐ๋ฅผ mutable๋กœ ์‚ฌ์šฉํ•˜๋ ค๋ฉด &mut์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
fn main() {
    let mut s = String::from("hello");

    change(&mut s);
}

fn change(some_string: &mut String) {
    some_string.push_str(", world");
}
  • ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์†Œ์œ ๊ถŒ์„ ๋„˜๊ธฐ์ง€ ์•Š์œผ๋ฏ€๋กœ, ์—ฌ๋Ÿฌ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
fn main() {
    let mut s = String::
    from("hello");
    
    let r1 = &mut s;
    let r2 = &mut s;
    
    println!("{}, {}", r1, r2);
}
$ cargo run
   Compiling ownership v0.1.0 (file:///projects/ownership)
error[E0499]: cannot borrow `s` as mutable more than once at a time
  --> src/main.rs:5:17
    |
4   |     let r1 = &mut s;

5   |     let r2 = &mut s;
    |                 ^^^^ mutable borrow starts here in previous iteration of loop 
      
6   |
7   |     println!("{}, {}", r1, r2);
    |                        -- borrow later used here
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
    
error: aborting due to previous error

For more information about this error, try `rustc --explain E0499`.
error: could not compile `ownership` due to previous error
  • ์‹ค์ œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š”๋ฐ ๊ฐ€์žฅ ํž˜๋“ค๊ฒŒ ๋Š๊ปด์ง€๋Š” ์ œ์•ฝ์‚ฌํ•ญ ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

  • ๋Ÿฌ์ŠคํŠธ๋Š” ์ด๋Ÿฌํ•œ ์ œ์•ฝ์‚ฌํ•ญ์„ ํ†ตํ•ด ๋ฉ”๋ชจ๋ฆฌ ์•ˆ์ •์„ฑ์„ ๋ณด์žฅํ•œ๋‹ค.

  • ์ •ํ™•ํžˆ๋Š” ๋Ÿฌ์ŠคํŠธ๋Š” ๋ฐ์ดํ„ฐ ๋ ˆ์ด์Šค๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ด๋Ÿฌํ•œ ์ œ์•ฝ์‚ฌํ•ญ์„ ๋‘๊ณ  ์žˆ๋‹ค.

  • ๋ฐ์ดํ„ฐ ๋ ˆ์ด์Šค๋Š” ๋‘๊ฐœ ์ด์ƒ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ๊ฐ™์€ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ์ด๋‹ค.

    • ๋™์‹œ์— ๊ฐ™์€ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๋ฉด์„œ, ์ ์–ด๋„ ํ•˜๋‚˜์˜ ์ ‘๊ทผ์ด ์“ฐ๊ธฐ์ผ ๋•Œ, ๋™์‹œ์„ฑ ๋กœ์ง์ด ์—†๋Š” ๊ฒฝ์šฐ์— ๋ฐœ์ƒํ•œ๋‹ค.
  • ๋Ÿฌ์ŠคํŠธ๋Š” ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•œ๋‹ค.

fn main() {
    let mut s = String::("hello");
    
    {
        let r1 = &mut s;
    } // r1 goes out of scope here, so we can make a new reference with no problems.
    
    let r2 = &mut s;
  • ๋‹ค์ˆ˜์˜ ์ฐธ์กฐ๊ฐ€ ํ•„์š” ํ•  ๋•Œ, ์œ„์™€ ๊ฐ™์ด ๋ธ”๋ก์„ ์‚ฌ์šฉํ•˜์—ฌ ์Šค์ฝ”ํ”„๋ฅผ ๋‚˜๋ˆ„์–ด ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

  • ์ฐธ์กฐ์˜ ๋ฒ”์œ„๋ฅผ ์ œํ•œํ•จ์œผ๋กœ์จ, ๋ฐ์ดํ„ฐ ๋ ˆ์ด์Šค๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๋˜ ํ•˜๋‚˜์˜ ์ œ์•ฝ์‚ฌํ•ญ์€ ๋ถˆ๋ณ€ ์ฐธ์กฐ์™€ ๊ฐ€๋ณ€ ์ฐธ์กฐ๋ฅผ ๋™์‹œ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

fn main() {
    let mut s = String::from("hello");
    
    let r1 = &s;
    let r2 = &s;
    let r3 = &mut s; // error
}
  • ๋ถˆ๋ณ€ ์ฐธ์กฐ๊ฐ’์ด ์žˆ๋Š” ๋™์•ˆ์—๋Š” ๊ฐ€๋ณ€ ์ฐธ์กฐ๋กœ ์ธํ•ด์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋Š”๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ง‰์•„๋‘” ๊ฒƒ์ด๋‹ค.

  • ์ถ”๊ฐ€์ ์œผ๋กœ ๋Ÿฌ์ŠคํŠธ๋Š” ์ปดํŒŒ์ผ ์‹œ์ ์— ๋ถˆ๋ณ€ ์ฐธ์กฐ์˜ ๋งˆ์ง€๋ง‰ ์‚ฌ์šฉ ์œ„์น˜ ์ดํ›„์—๋Š” ๊ฐ€๋ณ€ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค.

fn main() {
    let mut s = String::from("hello");
    
    let r1 = &s;
    let r2 = &s;
    println!("{} and {}", r1, r2);
    // r1 and r2 are no longer used after this point
    
    let r3 = &mut s;
}

4.2.1 Dangling References

  • Dangling References๋Š” ์ฐธ์กฐ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•ด์ œ๋œ ๊ฒฝ์šฐ๋ฅผ ๋งํ•œ๋‹ค.

    • ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ ํ›„์—๋„ ์ฐธ์กฐ๊ฐ€ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ,
    • ๋ฒ”์œ„ ๋ฐ– ์ฐธ์กฐ๊ฐ€ ์ผ์–ด๋‚˜๋Š” ๊ฒฝ์šฐ,
    • ๋ณต์‚ฌ๋œ ํฌ์ธํ„ฐ๊ฐ€ ์ผ์œผํ‚ค๋Š” ๊ฒฝ์šฐ ๋“ฑ์ด ์žˆ๋‹ค.
  • ๋Ÿฌ์ŠคํŠธ๋Š” ์ฐธ์กฐ๊ฐ€ ์œ ํšจํ•œ ๋™์•ˆ์—๋Š” ๋ฐ˜๋“œ์‹œ ๋ฐ์ดํ„ฐ๊ฐ€ ์Šค์ฝ”ํ”„ ๋‚ด์— ์žˆ๋„๋ก ๋ณด์žฅํ•œ๋‹ค.

  • ์ฆ‰, ๋ฐ์ดํ„ฐ๊ฐ€ ์ฐธ์กฐ๋ณด๋‹ค ๋จผ์ € ์Šค์ฝ”ํ”„ ๋ฐ–์œผ๋กœ ๋ฒ—์–ด๋‚˜์„œ๋Š” ์•ˆ ๋˜๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ๋Œ•๊ธ€๋ง ์ฐธ์กฐ๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ์ปดํŒŒ์ผ ์‹œ์ ์— ๋ฐฉ์ง€ํ•œ๋‹ค.

  • ์˜ˆ๋ฅผ๋“ค์–ด ํ•จ์ˆ˜๊ฐ€ ๋กœ์ปฌ ๋ณ€์ˆ˜์˜ ์ฐธ์กฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ, ๋Ÿฌ์ŠคํŠธ๋Š” ์ปดํŒŒ์ผ ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

fn main() {
    let reference_to_nothing = dangle();
}

fn dangle() -> &String { 
    let s = String::from("hello");
    &s 
}

4.3 The Slice Type

  • ์Šฌ๋ผ์ด๋“œ๋Š” ์ฐธ์กฐ์˜ ์ผ์ข…์œผ๋กœ, ์˜ค๋„ˆ์‰ฝ์„ ๊ฐ€์ง€์ง€ ์•Š๋Š”๋‹ค.

  • ์˜ˆ์‹œ : ๋ฌธ์ž์—ด์—์„œ ์ฒซ ๋‹จ์–ด๋ฅผ ์ฐพ๋Š” ํ•จ์ˆ˜ ๋งŒ๋“ค์–ด๋ณด๊ธฐ (๊ณต๋ฐฑ์„ ๊ธฐ์ค€์œผ๋กœ)

fn first_word(s: &String) -> ?
  • ์ด ํ•จ์ˆ˜๋Š” ๋ฌธ์ž์—ด์˜ ์ฐธ์กฐ๋ฅผ ๋ฐ›๋Š”๋ฐ, ๋ฌด์—‡์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ• ๊นŒ?
fn first_word(s: &String) -> usize {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return i;
        }
    }

    s.len()
}
let bytes = s.as_bytes(); // as_bytes() ๋ฉ”์†Œ๋“œ๋Š” ๋ฌธ์ž์—ด์„ ๋ฐ”์ดํŠธ ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.
for (i, &item) in bytes.iter().enumerate() // iter() ๋ฉ”์†Œ๋“œ๋Š” ์ปฌ๋ ‰์…˜์„ ๋ฐ˜๋ณตํ•˜๋Š” ๋ฐ˜๋ณต์ž๋ฅผ ์ƒ์„ฑํ•œ๋‹ค, enumerate() ๋ฉ”์†Œ๋“œ๋Š” ๋ฐ˜๋ณต์ž๋ฅผ ํŠœํ”Œ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.
  • ๋ฌธ์ž์—ด์˜ ์ธ๋ฑ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค,
fn main() {
    let mut s = String::from("hello world");

    let word = first_word(&s); // word will get the value 5

    s.clear(); // this empties the String, making it equal to ""

    // word still has the value 5 here, but there's no more string that
    // we could meaningfully use the value 5 with. word is now totally invalid!
}

4.3.1 String Slices

  • ์Šฌ๋ผ์ด์Šค๋Š” ๋ฌธ์ž์—ด์˜ ์ผ๋ถ€๋ถ„์„ ์ฐธ์กฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๊ณ  ์ด๋ ‡๊ฒŒ ์ƒ๊ฒผ๋‹ค.
let s = String::from("hello world");

let hello = &s[0..5];
let world = &s[6..11];

image

Rather than a reference to the entire String, hello is a reference to a portion of the String, specified in the extra [0..5] bit. We create slices using a range within brackets by specifying [starting_index..ending_index], where starting_index is the first position in the slice and ending_index is one more than the last position in the slice. Internally, the slice data structure stores the starting position and the length of the slice, which corresponds to ending_index minus starting_index. So, in the case of let world = &s[6..11];, world would be a slice that contains a pointer to the byte at index 6 of s with a length value of 5.

let s = String::from("hello");

let slice = &s[0..2];
let slice = &s[..2];

let len = s.len();

let slice = &s[3..len];
let slice = &s[3..];

let slice = &s[0..len];
let slice = &s[..];
fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }

    &s[..]
}
  • ๋˜‘๊ฐ™์ด ๊ฐœ๋…์ ์œผ๋กœ๋Š” ์ธ๋ฑ์Šค๋ฅผ ํ†ตํ•ด ๋ฌธ์ž์—ด์„ ์ฐพ๋Š” ๋ฐฉ์‹์ด์ง€๋งŒ, ์ฐธ์กฐ๋ฅผ ์—ฎ์–ด๋‘๋ฉด ํ›จ์”ฌ ๋” ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์ŠคํŠธ๋ง์ด ์œ ํšจํ•œ ๋™์•ˆ์— ์Šฌ๋ผ์ด์Šค๋„ ์œ ํšจํ•˜๋‹ค.

fn main() {
    let mut s = String::from("hello world");

    let word = first_word(&s);

    s.clear(); // error!

    println!("the first word is: {}", word);
}
$ cargo run
   Compiling ownership v0.1.0 (file:///projects/ownership)
error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable
  --> src/main.rs:18:5
   |
16 |     let word = first_word(&s);
   |                           -- immutable borrow occurs here
17 |
18 |     s.clear(); // error!
   |     ^^^^^^^^^ mutable borrow occurs here
19 |
20 |     println!("the first word is: {}", word);
   |                                       ---- immutable borrow later used here

For more information about this error, try `rustc --explain E0502`.
error: could not compile `ownership` due to previous error
  • String์˜ ๋‚ด์šฉ์„ ์ง€์šฐ๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ•ด๋‹น String์— ๋Œ€ํ•œ ๊ฐ€๋ณ€ ์ฐธ์กฐ๊ฐ€ ํ•„์š”ํ•œ๋ฐ, ๋งŒ์•ฝ ์ด๋ฏธ ๋ถˆ๋ณ€ ์ฐธ์กฐ๊ฐ€ ์กด์žฌํ•œ๋‹ค๋ฉด

  • clear ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ String์˜ ๋‚ด์šฉ์„ ๋ณ€๊ฒฝํ•˜๋ ค๊ณ  ํ•  ๋•Œ ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

  • ์ด๋Š” println! ๋งคํฌ๋กœ๊ฐ€ word์—์„œ ๋ถˆ๋ณ€ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•œ๋‹ค.

  • ๋”ฐ๋ผ์„œ, clear ํ•จ์ˆ˜๊ฐ€ ๊ฐ€๋ณ€ ์ฐธ์กฐ๋ฅผ ์š”๊ตฌํ•˜๋Š” ๋™์•ˆ word์˜ ๋ถˆ๋ณ€ ์ฐธ์กฐ๊ฐ€ ์—ฌ์ „ํžˆ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.

  • ๋Ÿฌ์ŠคํŠธ๋Š” ๊ฐ€๋ณ€ ์ฐธ์กฐ์™€ ๋ถˆ๋ณ€ ์ฐธ์กฐ๊ฐ€ ๋™์‹œ์— ์กด์žฌํ•˜๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ปดํŒŒ์ผ์ด ์‹คํŒจํ•œ๋‹ค.

  • ๊ฒฐ๋ก ์ ์œผ๋กœ String Literal์€ ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์œ„ ์ฝ”๋“œ์—์„œ s์˜ ํƒ€์ž…์€ &str์ž…๋‹ˆ๋‹ค. ์ด๋Š” ํŠน์ • ์ด์ง„ ํŒŒ์ผ ๋‚ด์˜ ์œ„์น˜๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์Šฌ๋ผ์ด์Šค๋กœ, ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์ด ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌ๋˜๋Š”์ง€๋ฅผ ๋ช…ํ™•ํžˆ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์ด ๋ถˆ๋ณ€์ธ ์ด์œ ๋„ ์—ฌ๊ธฐ์— ์žˆ์Šต๋‹ˆ๋‹ค &str์€ ๋ถˆ๋ณ€ ์ฐธ์กฐ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.๋”ฐ๋ผ์„œ, ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์€ ํ”„๋กœ๊ทธ๋žจ์˜ ์ด์ง„ ํŒŒ์ผ ๋‚ด์— ์ง์ ‘ ์ €์žฅ๋˜๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ์ƒ์„ฑ๋œ &str ํƒ€์ž…์˜ ๋ณ€์ˆ˜๋Š” ์ด์ง„ ํŒŒ์ผ ๋‚ด ํ•ด๋‹น ๋ฌธ์ž์—ด์˜ ์œ„์น˜๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ถˆ๋ณ€์˜ ์Šฌ๋ผ์ด์Šค๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํŠน์„ฑ์€ ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์ด ์™œ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š”์ง€(immutable)๋ฅผ ์„ค๋ช…ํ•ด ์ค๋‹ˆ๋‹ค.

let s = "Hello, world!";
  • ์ฐธ๊ณ ๋กœ ๊ฒฝํ—˜ ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹œ๊ทธ๋‹ˆ์ฒ˜๋ฅผ ์œ ์—ฐํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.
fn first_word(s: &str) -> &str
  • ์œ„์ฒ˜๋Ÿผ s ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ํƒ€์ž…์œผ๋กœ ๋ฌธ์ž์—ด ์Šฌ๋ผ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค.

  • ์ด๋ฅผ ํ†ตํ•ด ๋ฌธ์ž์—ด ์Šฌ๋ผ์ด์Šค๋ฅผ ์ง์ ‘ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๊ณ , String์ด ์žˆ์„ ๊ฒฝ์šฐ String์˜ ์Šฌ๋ผ์ด์Šค๋‚˜ String์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

  • ์ด๋Ÿฌํ•œ ์œ ์—ฐ์„ฑ์€ ์—ญ์ฐธ์กฐ ๊ฐ•์ œ ๋ณ€ํ™˜(deref coercions)์ด๋ผ๋Š” ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋‚˜์ค‘์—

fn main() {
    let my_string = String::from("hello world");

    // `first_word` works on slices of `String`s, whether partial or whole
    let word = first_word(&my_string[0..6]);
    let word = first_word(&my_string[..]);
    // `first_word` also works on references to `String`s, which are equivalent
    // to whole slices of `String`s
    let word = first_word(&my_string);

    let my_string_literal = "hello world";

    // `first_word` works on slices of string literals, whether partial or whole
    let word = first_word(&my_string_literal[0..6]);
    let word = first_word(&my_string_literal[..]);

    // Because string literals *are* string slices already,
    // this works too, without the slice syntax!
    let word = first_word(my_string_literal);
}