[C++] R-Value Reference์™€ Move Semantic

R-Value Reference(์ดํ•˜ ์˜ค๋ฅธ๊ฐ’ ์ฐธ์กฐ)๋Š” C++11๋ถ€ํ„ฐ ์ถ”๊ฐ€๋œ ์•„์ฃผ ๋ณต์žกํ•˜๋ฉด์„œ๋„ ๋ฉ‹์ง„ ๋…€์„์ด๋‹ค.

์ด๊ฒŒ ๋Œ€์ฒด ๋ญํ•˜๋Š” ๋†ˆ์ธ๊ณ  ํ•˜๋ฉด, ์•„์ฃผ ์›๋ก ์ ์ธ ๋ถ€๋ถ„๊นŒ์ง€ ์ ‘ํ•ด๋“ค์–ด๊ฐˆ ํ•„์š”๊ฐ€ ์žˆ๋‹ค.
์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ๋ด๋ณด์ž.
int num;
num = 33;
L: ์—ฌ๊ธฐ์„œ num์€ ์™ผ์ชฝ์— ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋ฆ„์ด ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ‘œํ˜„์‹์ด ์ข…๋ฃŒ๋˜์–ด๋„ ์กด์žฌํ•œ๋‹ค. ๋˜ํ•œ ๋ฉ”๋ชจ๋ฆฌ ์…€์ด๋ฏ€๋กœ ์ฃผ์†Œ์—ฐ์‚ฐ(&)์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๊ฒƒ์ด ์™ผ๊ฐ’์ด๋‹ค.
R: ์˜ค๋ฅธ์ชฝ์—๋Š” 33์ด ์žˆ๋‹ค. ์ด๊ฑด ์ด๋ฆ„์ด ์—†๋‹ค. ๊ทธ๋ƒฅ ๊ฐ’์ด num์œผ๋กœ ์ „๋‹ฌ๋  ๋ฟ์ด๊ณ , ํ‘œํ˜„์‹์ด ๋๋‚˜๋ฉด ์ฆ๋ฐœํ•œ๋‹ค. ๋˜ํ•œ ์ƒ์ˆ˜์ด๋ฏ€๋กœ ์ฃผ์†Œ์—ฐ์‚ฐ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค. ์ด๊ฒƒ์ด ์˜ค๋ฅธ๊ฐ’์ด๋‹ค.

const string& s... ๊ฐ™์€,
์ด์ œ๊นŒ์ง€ ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ–ˆ๋˜ ์ฐธ์กฐ๋Š” ์™ผ๊ฐ’์ฐธ์กฐ์˜€๋‹ค.
๊ธฐ์กด์— ์กด์žฌํ•˜๋˜ ๋ณ€์ˆ˜(์™ผ๊ฐ’)๋ฅผ ์ฐธ์กฐํ–ˆ์œผ๋‹ˆ๊นŒ.

ํ•˜์ง€๋งŒ ์ด์ œ ์šฐ๋ฆฌ๊ฐ€ ์ ‘๊ทผํ•ด๋ณผ ์˜ค๋ฅธ๊ฐ’ ์ฐธ์กฐ๋Š” ์ €๋Ÿฐ ์ด๋ฆ„์—†๋Š” ์ž„์‹œ ๊ฐ’๋“ค๋งˆ์ € ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.
ํ‘œ๊ธฐ๋ฒ•์€ ์•„๋ž˜์™€ ๊ฐ™์ด, &๋Œ€์‹ ์— &&๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
int && ref = 333; //์˜ค๋ฅธ๊ฐ’ 333์„ ์ฐธ์กฐ

์™ผ๊ฐ’๋„ std::move๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์˜ค๋ฅธ๊ฐ’ ์ฐธ์กฐ์— ๋ฌถ์„์ˆ˜ ์žˆ๋‹ค.
std::string s = "text";
std::string&& ref = std::move(s);
//์ด๋ฆ„์ด move์ง€๋งŒ ์ง„์งœ ์ด๋™ํ•˜๋Š”๊ฑด ์•„๋‹ˆ๊ณ  &&์ฐธ์กฐ๋กœ ์บ์ŠคํŒ…๋งŒ ํ•ด์คŒ

์˜ค๋ฅธ๊ฐ’ ์ฐธ์กฐ์ž๋„ ๊ธฐ์กด์˜ ์™ผ๊ฐ’ ์ฐธ์กฐ์ž์ฒ˜๋Ÿผ ๊ฐ’์— ์ ‘๊ทผํ•ด์„œ ์ด๋ž˜์ €๋ž˜ ์“ธ์ˆ˜ ์žˆ๋‹ค. image

image ๊ทผ๋ฐ ์ด๊ฒŒ ๋‹ค๋ผ๋ฉด ์ด๊ฑธ ๊ตฌ๋ถ„ํ•ด์„œ ์“ธ ์ด์œ ๊ฐ€ ์ „ํ˜€ ์—†๋‹ค. ๊ทธ๋ƒฅ ์™ผ๊ฐ’์ฐธ์กฐ ์จ๋„ ๋˜‘๊ฐ™์ด ๋˜์ž–์•„?


๊ทธ๋ ‡๋‹ค. ์ด ์˜ค๋ฅธ๊ฐ’ ์ฐธ์กฐ๋กœ ๊ฐ’์ด ๋‹ค๋ฅธ ๋ณ€์ˆ˜์— ์ „๋‹ฌ๋˜๊ณ , ๊ทธ ๋ณ€์ˆ˜์˜ ํƒ€์ž…์— ํ•ด๋‹นํ•˜๋Š” ์ด๋™ ์ƒ์„ฑ์ž(ํ˜น์€ ๋Œ€์ž…์ž)๊ฐ€ ์žˆ๋‹ค๋ฉด, **๋ฌด๋ธŒ ์‹œ๋งจํ‹ฑ(Move Semantic)**์ด๋ผ๋Š” ๊ฒƒ์ด ๋ฐœ์ƒํ•œ๋‹ค.
๋ง ๊ทธ๋Œ€๋กœ ์ด๋™(move)์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

์ปดํ“จํ„ฐ์—์„œ ๋ฌด๊ฑฐ์šด ์˜์ƒ ํŒŒ์ผ๋“ค์„ ์˜ฎ๊ฒจ๋ณธ ์ ์ด ์žˆ์„๊ฒƒ์ด๋‹ค.
ํŒŒ์ผ์ด ๋„ˆ๋ฌด ๋ฌด๊ฒ๋‹ค๋ฉด ๊ทธ ํŒŒ์ผ์˜ ๋ณต์‚ฌํ•˜๊ณ  ๋ถ™์—ฌ๋„ฃ๋Š”(Ctrl+c,v) ์†๋„๋„ ์—„์ฒญํ•˜๊ฒŒ ๋А๋ ค์ง„๋‹ค.
ํ•˜์ง€๋งŒ ํŒŒ์ผ์„ ์ž˜๋ผ๋‚ด๊ณ  ๋ถ™์ผ(Ctrl+x,v) ๋•Œ๋Š” ๋ณ„๋‹ค๋ฅธ ์‹œ๊ฐ„์ด ์†Œ์š”๋˜์ง€ ์•Š๊ณ  ๋š๋”ฑ ์™„๋ฃŒ๋œ๋‹ค. ์ด๊ฒƒ์ด ํŒŒ์ผ์ด ํ•œ ๊ตฐ๋ฐ๋งŒ ์กด์žฌํ•  ๊ฒƒ์„ ๋ณด์žฅํ•˜๋Š” ๋ฐ์„œ ๋ฐœ์ƒํ•˜๋Š” ์ผ์ข…์˜ ์ด๋™์ด๋‹ค.
์•ž์„œ ์–ธ๊ธ‰ํ•œ ๋ฌด๋ธŒ์‹œ๋งจํ‹ฑ๋„ ์ด์™€ ๊ฐ™์€ ์›๋ฆฌ๋ผ ๋ณด๋ฉด ๋œ๋‹ค.

์˜ˆ์‹œ๋ฅผ ํ•œ๋ฒˆ ๋ณด์ž.
//๊ฐ€์ •1: s ์•ˆ์— ๋‹ด๊ธด ๋ฌธ์ž์—ด์€ ํฌ๊ธฐ๊ฐ€ ํฌ๋‹ค.
std::string s = "...";
//์ด ์‹œ์ ์—์„œ s๋Š” ๋”์ด์ƒ ํ•„์š”๊ฐ€ ์—†๋‹ค.
//s2์—์„œ ์˜ฎ๊ฒจ์„œ s2๋กœ๋งŒ ์“ฐ๋ฉด ๋œ๋‹ค.
std::string s2 = s;

์ด๋Ÿฌ๋ฉด s2์˜ ๋ณต์‚ฌ์ƒ์„ฑ์ž๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด์„œ s์˜ ๋‚ด๋ถ€๊ฐ’์„ ์ผ์ผ์ด ๋ณต์‚ฌํ•ด์„œ ๊ฐ€์ ธ๊ฐ„๋‹ค.
๊ธฐ์กด s์˜ ํฌ๊ธฐ๊ฐ€ ํด์ˆ˜๋ก ์†Œ์š”๋˜๋Š” ์‹œ๊ฐ„๋„ ์„ ํ˜•์ ์œผ๋กœ ์ฆ๊ฐ€ํ•  ๊ฒƒ์ด๋‹ค.

ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ํ•œ๋‹ค๋ฉด
std::string s2 = std::move(s);
//s๋ฅผ std::string&&์œผ๋กœ ์บ์ŠคํŒ…
//s2์˜ ์ด๋™์ƒ์„ฑ์ž ํ˜ธ์ถœ

s์˜ ๊ธธ์ด์™€ ์ƒ๊ด€์—†์ด ์ด ์ž‘์—…์€ ์•„์ฃผ ์ž‘์€ ์ƒ์ˆ˜์‹œ๊ฐ„์— ์ข…๋ฃŒ๋œ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๊ธฐ์กด์˜ s๋Š” ํ…… ๋น„๊ฒŒ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋ฌด๋ธŒ์‹œ๋งจํ‹ฑ์€ ์—ฐ์‚ฐ์ค‘์— ๋ฐœ์ƒํ•œ ์ž„์‹œ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฃฐ๋•Œ๋„ ํšจ์šฉ์„ ๋ณด์ธ๋‹ค.
std::string s = "hello";
std::string s2 = " world";
std::string s3 = s+s2;
์˜›๋‚  ๋ฐฉ์‹๋Œ€๋กœ ์ƒ๊ฐํ•ด๋ณด์ž. ์œ„ ์ฝ”๋“œ์˜ ์„ธ๋ฒˆ์งธ์ค„์—์„œ s์™€ s2๊ฐ€ ๋”ํ•ด์ ธ์„œ ๋‘˜์ด ์ด์–ด์ง„ ์ž„์‹œ๊ฐ์ฒด std::string("hello world")๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค. ์—ฌ๊ธฐ๊นŒ์ง„ ์ข‹๋‹ค. ๊ทธ๋Ÿผ
std::string s3 = std::string("hello world");
์˜ ํ˜•ํƒœ๊ฐ€ ๋œ๋‹ค.
๊ทธ๋Ÿผ ์ € ์ž„์‹œ๊ฐ์ฒด์˜ ๊ฐ’์„ ๋ณต์‚ฌํ•ด๊ฐ€๊ธฐ ์œ„ํ•ดย  ๋ณต์‚ฌ์ƒ์„ฑ์ž๊ฐ€ ํ˜ธ์ถœ๋˜๊ณ  ์ € ๊ฐ’๋“ค์„ ์ „๋ถ€ ๋ณต์‚ฌํ•ด๊ฐˆ ๊ฒƒ์ด๋‹ค.
๋‹น์žฅ ์ € ๊ธธ์ด๋ผ๋ฉด ์ƒ๊ด€์—†์ง€๋งŒ, ์ž„์‹œ๊ฐ์ฒด๊ฐ€ ์ €๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ํฌ๋‹ค๋ฉด ์ด๊ฑด ๋ฌธ์ œ๊ฐ€ ๋œ๋‹ค.

ํ•˜์ง€๋งŒ ์ด์ œ ์šฐ๋ฆฌ์—๊ฒ ๋ฌด๋ธŒ ์‹œ๋งจํ‹ฑ์ด ์žˆ๋‹ค.
s+s2์˜ ๊ฒฐ๊ณผ๋ฌผ์€ ์˜ค๋ฅธ๊ฐ’์ด๋‹ค.
๊ทธ๋Ÿฌ๋ฏ€๋กœ ์ด๋™์ƒ์„ฑ์ž๊ฐ€ ํ˜ธ์ถœ๋ผ์„œ s+s2์˜ ๊ฒฐ๊ณผ๊ฐ’์ด ๋‚ญ๋น„์—†์ด s3์—๊ฒŒ ์™ ๋„˜์–ด๊ฐ„๋‹ค.


๊ทธ๋ฆฌ๊ณ  ์ด๋Ÿฐ ์„ฑ๋Šฅ์˜ ํ–ฅ์ƒ ๋นผ๊ณ ๋„, ์ด ๋ฌด๋ธŒ์‹œ๋งจํ‹ฑ์€ ํ•˜๋‚˜์˜ ์žฅ์ ์ด ๋˜ ์žˆ๋‹ค.

๋ฌด๋ธŒ์‹œ๋งจํ‹ฑ์€ ๋ง ๊ทธ๋Œ€๋กœ ์ด๋™์ด๋‹ค.
๊ฐ’์ด ์•„๋ž˜์— ์žˆ๋˜ ๊ฒƒ์ด ์œ„๋กœ ๊ฐ€๋ฉด, ๊ทธ ๊ฐ’์€ ์œ„์—๋งŒ ์กด์žฌํ•œ๋‹ค. ์•„๋ž˜์—๋Š” ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค.
๊ทธ๋Ÿฌ๋ฏ€๋กœ ์ด๋™์˜ ๋™์ž‘์€ ์˜๋ฏธ๋ก ์ ์œผ๋กœ ์œ ์ผ์„ฑ(unique)์„ ๋ณด์žฅํ•œ๋‹ค. ๋ณต์‚ฌ์™€ ๋‹ค๋ฅด๊ฒŒ.

๊ทธ๋ž˜์„œ ์Šค๋งˆํŠธํฌ์ธํ„ฐ std::unique_ptr ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ์ด๋Ÿฐ ์ด๋™๋งŒ์„ ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ณต์‚ฌ๋Š” ๊ธˆ์ง€๋˜์–ด์žˆ๋‹ค.
์ด ์™ธ์—๋„ ๋ณต์‚ฌ๋Š” ๊ธˆ์ง€ํ•˜๊ณ  ์ด๋™๋งŒ์„ ํ—ˆ๊ฐ€ํ•˜๋Š” ํด๋ž˜์Šค๋“ค์ด ๊ฝค ์žˆ๋‹ค.
auto p = std::make_unique(...);
std::unique_ptr p2 = p; //์—๋Ÿฌ! ๋ณต์‚ฌ ๋ถˆ๊ฐ€
std::unique_ptr p3 = std::move(p); //p->p3 ์ด๋™. p๋Š” null์ด ๋จ


์•„ ๊ทธ๋ฆฌ๊ณ  ์˜ค๋ฅธ๊ฐ’์ฐธ์กฐ๊ฐ€ ๋“ฑ์žฅํ•˜๋ฉด์„œ ์›๋ž˜ 4๊ฐœ์˜€๋˜ ํด๋ž˜์Šค์˜ ๊ธฐ๋ณธ ํ•จ์ˆ˜๋“ค์ด, 6๊ฐœ๋กœ ๋Š˜์–ด๋‚ฌ๋‹ค.
ํด๋ž˜์Šค๋ช…์ด T์ผ ๊ฒฝ์šฐ, ๊ธฐ๋ณธ ํ•จ์ˆ˜๋“ค์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.
**T()=default; **//๊ธฐ๋ณธ ์ƒ์„ฑ์ž
~T() = default; //์†Œ๋ฉธ์ž
T(const T&) = default;
//๋ณต์‚ฌ์ƒ์„ฑ์ž

**T(T&&) = default; **//์ด๋™์ƒ์„ฑ์ž
**T& operator=(const T&) = default; **//๋ณต์‚ฌ๋Œ€์ž…์ž
**T& operator=(T&&) = default; **//์ด๋™๋Œ€์ž…์ž
์ด๋™์ƒ์„ฑ์ž์™€ ์ด๋™๋Œ€์ž…์ž๋Š” ๊ตฌํ˜„ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. ๋ณต์‚ฌ์ƒ์„ฑ์ž์™€ ๊ฐ™์€ ์–•์€๋ณต์‚ฌ์˜ ๋ฌธ์ œ๋Š” ์—†๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ƒฅ =default๋งŒ ํ•ด์ค˜๋„ ๋œ๋‹ค.(์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ์ž๋™๊ตฌํ˜„์‹œํ‚ค๊ธฐ)
๊ทธ๋ž˜๋„ ๋งŒ์•ฝ ๊ตฌํ˜„ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ์•„๋ž˜์ฒ˜๋Ÿผ ํ•˜๋ฉด ๋œ๋‹ค.
//๊ฐ€์ •: ํƒ€์ž… T์—๋Š” ๋ฉค๋ฒ„๋ณ€์ˆ˜๋กœ a์™€ b๋ฅผ ๊ฐ€์ง„๋‹ค.
//๊ฐ€์ •: a์™€ b๋Š” ์ „๋ถ€ ์ด๋™์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
T(T&& other) :
a(std::move(other.a)),
b(std::move(other.b)
{}
T& operator=(T&& other)
{
ย ย ย  this->a=std::move(other.a);
ย ย ย  this->b=std::move(other.b);
ย ย ย  return *this;
}

์•„๋ฌดํŠผ ์˜ค๋ฅธ๊ฐ’ ์ฐธ์กฐ๋Š” ๊ต‰์žฅํžˆ ์œ ์šฉํ•˜๋‹ค.
๋ฌธ์ œ๋Š” ์ž์ž˜ํ•œ ๊ทœ์น™๊ณผ ํ•จ์ •์ด ๋งŽ๊ณ , ๋ณต์žกํ•˜๋‹ค๋Š” ๊ฒƒ์ธ๋ฐ

๊ฐ€์žฅ ํ—ท๊ฐˆ๋ฆด๋งŒํ•œ ๊ฒƒ์€, ์˜ค๋ฅธ๊ฐ’ ์ฐธ์กฐ์ž๋Š” ์˜ค๋ฅธ๊ฐ’์ด ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์ด๋‹ค. ์˜ค๋ฅธ๊ฐ’ ์ฐธ์กฐ์ž ์ž์ฒด๋Š” ์ด๋ฆ„๋„ ์žˆ๊ณ , ์ฃผ์†Œ์—ฐ์‚ฐ๋„ ๊ฐ€ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํ‘œํ˜„์‹์ด ์ข…๋ฃŒ๋˜์–ด๋„ ์ƒ์กดํ•œ๋‹ค.
๋•Œ๋ฌธ์— ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ์ด๋™์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.
std::string s = "...";
std::string&& s2 = std::move(s); //s->s2 ์ด๋™
std::string s3 = s2; //s2->s3 ์ด๋™ ์‹คํŒจ. ๊ทธ๋ƒฅ ๋ณต์‚ฌ ์ƒ์„ฑ์ž ํ˜ธ์ถœ

์ด๋™์˜ ๊ณผ์ •์€ ์ˆœ์ˆ˜ํ•˜๊ฒŒ ์˜ค๋ฅธ๊ฐ’์œผ๋กœ๋งŒ ์ „๋‹ฌ๋˜์–ด์•ผ ํ•œ๋‹ค.
์•„๋ž˜์™€ ๊ฐ™์ด ๊ณ ์น˜๋ฉด ์ด๋™์ด ์ˆ˜ํ–‰๋œ๋‹ค.
std::string s = "...";
std::string&& s2 = std::move(s); //s->s2 ์ด๋™
std::string s3 = std::move(s2); //s2->s3 ์ด๋™

๊ทธ๋ฆฌ๊ณ  ์˜ค๋ฅธ๊ฐ’ ์ฐธ์กฐ์ž๋Š” const๋ฅผ ๋ถ™์ด๋ฉด ์•ˆ๋œ๋‹ค.
์—๋Ÿฌ๋Š” ๋‚˜์ง€ ์•Š์ง€๋งŒ ์ด๋™์ด ์‹คํŒจํ•œ๋‹ค.


๋” ์ž์„ธํ•œ ์‚ฌํ•ญ๋“ค์€ ๋ชจ๋˜ ์ดํŽ™ํ‹ฐ๋ธŒ C++๋ฅผ ์ฐธ์กฐํ•˜๊ธธ ๋ฐ”๋ž€๋‹ค.