๋นŒ๋ฆผ

As we saw before, instead of transferring ownership when calling a function, you can let a function borrow the value:

#[derive(Debug)]
struct Point(i32, i32);

fn add(p1: &Point, p2: &Point) -> Point {
    Point(p1.0 + p2.0, p1.1 + p2.1)
}

fn main() {
    let p1 = Point(3, 4);
    let p2 = Point(10, 20);
    let p3 = add(&p1, &p2);
    println!("{p1:?} + {p2:?} = {p3:?}");
}
  • add ํ•จ์ˆ˜๋Š” ๋‘ Point ๊ฐ์ฒด ๊ฐ’์„ _๋นŒ๋ ค_์™€์„œ ์ƒˆ๋กœ์šด Point ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • p1๊ณผ p2์˜ ์†Œ์œ ๊ถŒ์€ ์—ฌ์ „ํžˆ ํ˜ธ์ถœ์ž(mainํ•จ์ˆ˜)์— ์žˆ์Šต๋‹ˆ๋‹ค.
This slide should take about 10 minutes.

์ด ์Šฌ๋ผ์ด๋“œ๋Š” 1์ผ ์ฐจ์˜ ์ฐธ์กฐ๋ฅผ ๋‹ค๋ฃฌ ์ž๋ฃŒ๋ฅผ ๊ฒ€ํ† ํ•˜๋Š” ๊ฒƒ์œผ๋กœ, ์•ฝ๊ฐ„ ํ™•์žฅ๋˜์–ด ํ•จ์ˆ˜ ์ธ์ˆ˜์™€ ๋ฐ˜ํ™˜ ๊ฐ’์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

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

์Šคํƒ์— ํ• ๋‹น๋œ ๊ฐ’์„ ๋ฆฌํ„ดํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ์ฐธ๊ณ :

  • Demonstrate that the return from add is cheap because the compiler can eliminate the copy operation. Change the above code to print stack addresses and run it on the Playground or look at the assembly in Godbolt. In the โ€œDEBUGโ€ optimization level, the addresses should change, while they stay the same when changing to the โ€œRELEASEโ€ setting:

    #[derive(Debug)]
    struct Point(i32, i32);
    
    fn add(p1: &Point, p2: &Point) -> Point {
        let p = Point(p1.0 + p2.0, p1.1 + p2.1);
        println!("&p.0: {:p}", &p.0);
        p
    }
    
    pub fn main() {
        let p1 = Point(3, 4);
        let p2 = Point(10, 20);
        let p3 = add(&p1, &p2);
        println!("&p3.0: {:p}", &p3.0);
        println!("{p1:?} + {p2:?} = {p3:?}");
    }
  • ๋Ÿฌ์ŠคํŠธ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋ฐ˜ํ™˜๊ฐ’ ์ตœ์ ํ™”(RVO)๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • C++์—์„œ copy elision์€ ์ƒ์„ฑ์ž์˜ ๋ถ€์ˆ˜ํšจ๊ณผ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์–ด ์–ธ์–ด๋ ˆ๋ฒจ์˜ ์ •์˜๊ฐ€ ํ•„์š”ํ•˜์ง€๋งŒ ๋Ÿฌ์ŠคํŠธ์—์„œ๋Š” ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ RVO๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์œผ๋ฉด ๋Ÿฌ์ŠคํŠธ๋Š” ํ•ญ์ƒ ๊ฐ„๋‹จํ•˜๊ณ  ํšจ์œจ์ ์ธ memcpy๋ณต์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.