Move ๋ฌธ๋ฒ•

(๋ณ€์ˆ˜์˜) ํ• ๋‹น์€ _์†Œ์œ ๊ถŒ_์„ ๋ณ€์ˆ˜ ๊ฐ„์— ์ด๋™์‹œํ‚ต๋‹ˆ๋‹ค:

fn main() {
    let s1: String = String::from("Hello!");
    let s2: String = s1;
    println!("s2: {s2}");
    // println!("s1: {s1}");
}
  • s1์„ s2์— ํ• ๋‹นํ•˜์—ฌ ์†Œ์œ ๊ถŒ์„ ์ด์ „์‹œํ‚ต๋‹ˆ๋‹ค.
  • s1์˜ ์Šค์ฝ”ํ”„๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด ์•„๋ฌด ์ผ๋„ ์—†์Šต๋‹ˆ๋‹ค: ์™œ๋ƒํ•˜๋ฉด s1์€ ์•„๋ฌด๋Ÿฐ ์†Œ์œ ๊ถŒ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
  • s2์˜ ์Šค์ฝ”ํ”„๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด ๋ฌธ์ž์—ด ๋ฐ์ดํ„ฐ๋Š” ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค.

s2๋กœ ์ด๋™ ์ „ ๋ฉ”๋ชจ๋ฆฌ:

StackHeaps1ptrHello!len4capacity4

s2๋กœ ์ด๋™ ํ›„ ๋ฉ”๋ชจ๋ฆฌ:

StackHeaps1ptrHello!len4capacity4s2ptrlen4capacity4(inaccessible)

๊ฐ’์„ ํ•จ์ˆ˜์— ์ „๋‹ฌํ• ๋•Œ, ๊ทธ ๊ฐ’์€ ๋งค๊ฐœ๋ณ€์ˆ˜์— ํ• ๋‹น๋ฉ๋‹ˆ๋‹ค. ์ด๋•Œ ์†Œ์œ ๊ถŒ์˜ ์ด๋™์ด ์ผ์–ด๋‚ฉ๋‹ˆ๋‹ค:

fn say_hello(name: String) {
    println!("์•ˆ๋…•ํ•˜์„ธ์š” {name}")
}

fn main() {
    let name = String::from("Alice");
    say_hello(name);
    // say_hello(name);
}
This slide should take about 5 minutes.
  • ์ด๋Š” C++๊ณผ ์ •๋ฐ˜๋Œ€ ์ž„์„ ์„ค๋ช…ํ•˜์„ธ์š”. C++์—์„œ๋Š” ๋ณต์‚ฌ๊ฐ€ ๊ธฐ๋ณธ์ด๊ณ , std::move ๋ฅผ ์ด์šฉํ•ด์•ผ๋งŒ (๊ทธ๋ฆฌ๊ณ  ์ด๋™ ์ƒ์„ฑ์ž๊ฐ€ ์ •์˜๋˜์–ด ์žˆ์–ด์•ผ๋งŒ!) ์†Œ์œ ๊ถŒ ์ด์ „์ด ๋ฉ๋‹ˆ๋‹ค.

  • ์‹ค์ œ๋กœ ์ด๋™๋˜๋Š” ๊ฒƒ์€ ์†Œ์œ ๊ถŒ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ๋จธ์‹  ์ฝ”๋“œ ๋ ˆ๋ฒจ์—์„œ ๋ฐ์ดํ„ฐ ๋ณต์‚ฌ๊ฐ€ ์ผ์–ด๋‚  ์ง€ ๋ง ์ง€์— ๋Œ€ํ•œ ๊ฒƒ์€ ์ปดํŒŒ์ผ๋Ÿฌ ๋‚ด๋ถ€์—์„œ ์ผ์–ด๋‚˜๋Š” ์ตœ์ ํ™” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๋ณต์‚ฌ๋Š” ์ตœ์ ํ™” ๊ณผ์ •์—์„œ ์ œ๊ฑฐ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

  • ์ •์ˆ˜์™€ ๊ฐ™์€ ๊ฐ„๋‹จํ•œ ๊ฐ’๋“ค์€ Copy (๋’ค์— ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค)๋กœ ๋งˆํ‚น๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋Ÿฌ์ŠคํŠธ์—์„œ๋Š” ๋ณต์‚ฌํ• ๋•Œ์—๋Š” ๋ช…์‹œ์ ์œผ๋กœ clone์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

say_hello ์˜ˆ:

  • say_helloํ•จ์ˆ˜์˜ ์ฒซ๋ฒˆ์งธ ํ˜ธ์ถœ์‹œ mainํ•จ์ˆ˜๋Š” ์ž์‹ ์ด ๊ฐ€์ง„ name์— ๋Œ€ํ•œ ์†Œ์œ ๊ถŒ์„ ํฌ๊ธฐํ•˜๋ฏ€๋กœ, ์ดํ›„ mainํ•จ์ˆ˜์—์„œ๋Š” name์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  • name์— ํ• ๋‹น๋˜์žˆ๋Š” ํž™ ๋ฉ”๋ชจ๋ฆฌ๋Š” say_helloํ•จ์ˆ˜์˜ ๋์—์„œ ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค.
  • mainํ•จ์ˆ˜์—์„œ name์„ ์ฐธ์กฐ๋กœ ์ „๋‹ฌ(๋นŒ๋ฆผ)ํ•˜๊ณ (&name), say_hello์—์„œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ˜•์œผ๋กœ ์ˆ˜์ •ํ•œ๋‹ค๋ฉด mainํ•จ์ˆ˜๋Š” name์˜ ์†Œ์œ ๊ถŒ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋˜๋Š” ์ฒซ๋ฒˆ์งธ ํ˜ธ์ถœ ์‹œ mainํ•จ์ˆ˜์—์„œ name์„ ๋ณต์ œํ•˜์—ฌ ์ „๋‹ฌํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.(name.clone())
  • ๋Ÿฌ์ŠคํŠธ๋Š” ์ด๋™์„ ๊ธฐ๋ณธ์œผ๋กœ ํ•˜๊ณ  ๋ณต์ œ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์„ ์–ธํ•˜๋„๋ก ๋งŒ๋“ฌ์œผ๋กœ, ์˜๋„์น˜ ์•Š๊ฒŒ ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด C++์—์„œ๋ณด๋‹ค ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

๋” ์‚ดํŽด๋ณด๊ธฐ

Defensive Copies in Modern C++

Modern C++์€ ์ด ๋ฌธ์ œ๋ฅผ ๋‹ค๋ฅด๊ฒŒ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค:

std::string s1 = "Cpp";
std::string s2 = s1;  // s1์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณต์ œํ•ฉ๋‹ˆ๋‹ค.
  • s1์˜ ํž™ ๋ฐ์ดํ„ฐ๋Š” ๋ณต์ œ๋˜๊ณ , s2๋Š” ๋…๋ฆฝ์ ์ธ ๋ณต์‚ฌ๋ณธ์„ ์–ป์Šต๋‹ˆ๋‹ค.
  • s1 ์™€ s2์˜ ์Šค์ฝ”ํ”„๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด ๊ฐ๊ฐ์˜ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค.

๋ณต์‚ฌ ์ „:

StackHeaps1ptrCpplen3capacity3

๋ณต์‚ฌ ํ›„:

StackHeaps1ptrCpplen3capacity3s2ptrCpplen3capacity3

ํ‚ค ํฌ์ธํŠธ:

  • C++๋Š” Rust์™€ ์•ฝ๊ฐ„ ๋‹ค๋ฅธ ์„ ํƒ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค. =๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ณต์‚ฌํ•˜๋ฏ€๋กœ ๋ฌธ์ž์—ด ๋ฐ์ดํ„ฐ๊ฐ€ ํด๋ก ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋ฌธ์ž์—ด ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚  ๋•Œ double-free๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

  • C++์—๋Š” ๊ฐ’์„ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋Š” ์‹œ์ ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” std::move๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๊ฐ€ s2 = std::move(s1)์ด์—ˆ๋‹ค๋ฉด ํž™ ํ• ๋‹น์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋™ ํ›„์—๋Š” s1์ด ์œ ํšจํ•˜์ง€๋งŒ ์ง€์ •๋˜์ง€ ์•Š์€ ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. Rust์™€ ๋‹ฌ๋ฆฌ ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” s1์„ ๊ณ„์† ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Rust์™€ ๋‹ฌ๋ฆฌ, C++์˜ =๋Š” ๋ณต์‚ฌ๋˜๊ฑฐ๋‚˜ ์ด๋™๋˜๋Š” ํƒ€์ž…์— ๋”ฐ๋ผ ๊ฒฐ์ •๋œ ์ž„์˜์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.