C++/๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ (OOP)

[C++] Move Constructor | ์ด๋™ ์ƒ์„ฑ์ž

Chan Lee 2024. 1. 2. 00:49

INTRO

 

int total {0};
total = 100 + 200;

์œ„ ์ฝ”๋“œ์—์„œ total์€ ํฌ์ธํ„ฐ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋ณ€์ˆ˜ ๊ฐ’, L-Value์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  total์— ํ• ๋‹น๋˜๋Š” 100+200 ์ˆ˜์‹์€ ํฌ์ธํ„ฐ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” R-Value์ž…๋‹ˆ๋‹ค.

 

C++์—์„œ ์ด๋Ÿฐ ๊ฐ’๋“ค์€ ์ด๋ฆ„์—†๋Š” temp value๋กœ ์ผ์‹œ์ ์œผ๋กœ ์ €์žฅ๋˜์—ˆ๋‹ค๊ฐ€, 

total๊ณผ ๊ฐ™์€ ๊ฐ’์— ๋ณต์‚ฌ ์ €์žฅ๋˜๊ณ  ๋‚œ ๋’ค ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ๊ฐ™์€ ์ผ์ด temp value๋ฅผ temp object๋กœ๋งŒ ๋ฐ”๋€Œ์–ด์„œ ๊ฐ์ฒด์—์„œ๋„ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋ณต์‚ฌ ์ƒ์„ฑ์ž๋ฅผ ์ƒ๊ฐํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฐ๋ฐ, ๋ณต์‚ฌ ์ƒ์„ฑ์ž๋ฅผ ๋ฐ˜๋ณต์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋ฉด temporary object๊ฐ€ ๊ทธ๋งŒํผ ๋งŽ์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

๋ฐ˜๋ฉด ๊ฐ์ฒด๋Š” ์ƒ๋Œ€์ ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋งŽ์ด ์š”๊ตฌํ•ฉ๋‹ˆ๋‹ค.

Deep copy๋ฅผ ํ–‰ํ•˜๋ฉด ๋”์šฑ ๋งŽ์ด ์š”๊ตฌ๋˜๊ฒ ์ฃ ?

 

์ด๋Ÿฐ ์ด์œ ์—์„œ Move Semantics, Move Constructor (์ด๋™ ์ƒ์„ฑ์ž) ๊ฐ€ ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค.

 

 

์ด๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์šฐ์„  R-Value References์— ๋Œ€ํ•ด์„œ ์ดํ•ดํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

 

L-Value References์™€๋Š” ๋‹ค๋ฅด๊ฒŒ r-value references๋Š” double ampersand(&&) ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ง๊ด€์ ์ธ ์˜ˆ์‹œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

int x{100};
int &l_ref = x;	// l-value reference
l_ref = 50;

int &&r_ref = 500;	// r-value reference
r_ref = 300;

int &&x_ref = x;	// COMPILER ERROR

 

&l_ref ๋Š” single ampersand๋กœ ์„ ์–ธ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— l-value์ธ x๋ฅผ ๊ฐ’์œผ๋กœ ์ง€๋‹ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

&&r_ref๋Š” double ampersand๋กœ ์„ ์–ธ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— r-value์ธ 500์„ ๊ฐ’์œผ๋กœ ์ง€๋‹ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

&&๋กœ ์„ ์–ธ๋œ x_ref์— x๋ฅผ ์ €์žฅํ•˜๋ ค๊ณ  ํ•˜๋ฉด l-value ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

 

ํ•จ์ˆ˜์—์„œ๋„ ๋™์ผํ•˜๊ฒŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

int x {100};

void func(int &&num);

func(200);	// OK
func(x);	// COMPILE ERROR

 

r-value reference๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š” func์— ์ •์ˆ˜๋ฅผ ์ง์ ‘ ์ž…๋ ฅํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ์—†์ง€๋งŒ,

l-value์ธ ๋ณ€์ˆ˜๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

 

์—ฌ๊ธฐ๊นŒ์ง€ ์ดํ•ดํ•˜๊ณ  ์ด๋™ ์ƒ์„ฑ์ž๋ฅผ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


 

Move Constructor (์ด๋™ ์ƒ์„ฑ์ž)

 

์ด๋™ ์ƒ์„ฑ์ž๋Š” ๊ฐ์ฒด๋ฅผ ๋ณต์‚ฌํ•˜์ง€ ์•Š๊ณ  ์ด๋™์‹œํ‚ต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์€ ๋ฉ”๋ชจ๋ฆฌ์ ์ธ ์ธก๋ฉด์—์„œ ๋งค์šฐ ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.

 

์ด๋™ ์ƒ์„ฑ์ž์˜ ํ”„๋กœํ† ํƒ€์ž…๋“ค์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Type::Type(Type &&source);
Player::Player(Player &&source);
Move::Move(Move &&source);

 

๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๋˜ ๋ณต์‚ฌ ์ƒ์„ฑ์ž์™€ ์œ ์‚ฌํ•˜๊ฒŒ ๊ตฌ์กฐ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ฒซ๋ฒˆ์งธ ์ฐจ์ด์ ์€ const ํ‚ค์›Œ๋“œ๊ฐ€ ์—†๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.

์›๋ณธ ๊ฐ์ฒด์˜ ํฌ์ธํ„ฐ๋ฅผ null ์œผ๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

๋‘๋ฒˆ์งธ๋Š” ์ž…๋ ฅ ์ธ์ž๋กœ R-Value Reference ๋ฅผ ๋ฐ›๋Š”๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.

Double ampersand(&&)๋กœ ํ™•์ธ๋ฉ๋‹ˆ๋‹ค.

 

 

์ด ์ด๋™ ์ƒ์„ฑ์ž๋“ค์˜ ๊ตฌ์กฐ๋Š” ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

Move::Move(Move &&source) noexcept : data(source.data) { source.data = nullptr; }

 

Deep copying์œผ๋กœ ์ธํ•œ ํฐ ๋ฉ”๋ชจ๋ฆฌ ์š”๊ตฌ์—†์ด 

๊ธฐ์กด์˜ source.data๊ฐ€ ์ง€์นญํ•˜๋˜ ์ฃผ์†Œ์˜ ์†Œ์œ ๊ถŒ์„ ์ƒˆ๋กœ์šด ๊ฐ์ฒด์˜ data๊ฐ’์— ์ด์ „์‹œํ‚ต๋‹ˆ๋‹ค.

 

์ฆ‰, ๋ณต์‚ฌ๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ์˜ ๋ถˆ๊ฐ€ํ”ผํ•œ ๋ฉ”๋ชจ๋ฆฌ ์†Œ์š” ์—†์ด ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ค‘์š”ํ•œ ์ ์€ source.data = nullptr; ์„ ํ†ตํ•ด์„œ ๊ธฐ์กด์˜ ๊ฐ’์„ null๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ ์ž…๋‹ˆ๋‹ค.

 

nullptr๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ์ง€ ์•Š๋Š”๋‹ค๋ฉด shallow copying๊ณผ ๋™์ผํ•œ ํ–‰๋™์ž…๋‹ˆ๋‹ค.