(Cโบโบ) ๐คrvalue reference
๋๋ ์ ํผ์ ๋ ๋ณต์กํด์ง๊ณ ์๋(โฆMove ๋๋ฌธ์)
๋ง๊ทธ๋๋ก rvalue์ reference
์ด๋ค. ๋ฐ๋ผ์ ์ผ๋ฐ๋ณ์์ ๊ฐ์ lvalue๋ ์ฐธ์กฐํ์ง ๋ชปํ๋ค. (๋์ค universal reference
์๋ ๊ตฌ๋ถํ๋ค) ๋ค๋ง ์ด๋ ค์์ง๋ ๋ถ๋ถ์ rvalue์ ์ ์๊ฐ Modern C++๋ถํฐ ๊ต์ฅํ ๋ณต์กํด์ก๋ค๋ ์ ์ด๋ค. ๊ทธ๋ฆฌ๊ณ ๊ณ ์ ์ ์ธ rvalue๋ pure rvalue๋ก์ ํ๋์ ์์ญ์ ๋ถ๊ณผํด์ก๋ค.
๋ณธ์ง์ ์ผ๋ก ์ด๋ฐ ๋ณต์กํ ๊ฐ๋ ์ Move ์ฐ์ฐ์ ์ํด ์กด์ฌํ๋ค. ๊ทธ๊ฒ์ Rust์ฒ๋ผ ์์ ๊ถ ๊ฐ๋ ์ ํ์คํ ํ๊ธฐ ์ํจ์ด๋ค. ๊ณต์ ๋ฉ๋ชจ๋ฆฌ๋ ์ฌ์์ ์จ์์ด๋ค. (ํ์ง๋ง ์ด๋ ๊ฒ ๋ณต์กํ๋ฉด ์ฐจ๋ผ๋ฆฌ Rust๋ฅผ ์ฐ๋๊ฒ ์ด๋จ๊นโฆ)
๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ๋ก๋ฅผ ๋ณด๋ฉด ์๋์ ๊ฐ๋ค.
#include <iostream>
#include <algorithm>
using namespace std;
int&& foo() { return 10; }
void f(int&) { cout << "int&" << endl; }
void f(int&&) { cout << "int&&" << endl; }
int main()
{
int&& rr1 = 10;
int&& rr2 = foo();
f(10);
f(foo());
f(rr1);
f(rr2);
int n = 10;
f(n);
f(static_cast<int&&>(n));
f(move(n));
return 0;
}
&& ์ฐ์ฐ์
๋ก rvalue reference
๋ฅผ ์ ์ํ๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ ์ค rvalue reference๋ก ๋ณํํ๋ move ํจ์
์ ๋ํด ์ดํด๋ณด๋ฉด,
template <typename T>
T&& move(T t)
{
return static_cast<T&&>(t);
}
์ด ์ ๋๋ก ๊ตฌํ๋๋ค๊ณ ์ถ์ธกํ ์ ์๋ค. ์ฆ, ์ ์์ ์์ move ํจ์ ์ ๋ผ์ธ๊ณผ ๋์ผํ ๊ฒ์ด๋ค. move๋ผ๋ ํจ์์ ์ด๋ฆ์ ๊ด๋ จ์๋ ๊ฐ๋ ์ธ ์ด๋ ์์ฑ์์ ์ฐ๊ด์ด ์๋๊ฒ์ผ๋ก ๋ณด์ธ๋ค.
์์์๋ ์ ๊น ์ธ๊ธํ๋ universal reference
์ ๋ํด ์ดํด๋ณด๋ฉด, auto๋ template ์ธ์์ฒ๋ผ type์ ์ถ๋ก ํ๋ ๊ฒฝ์ฐ์๋ && ์ฐ์ฐ์๊ฐ lvalue์ rvalue๋ฅผ ๋ชจ๋ ๋ฐ์ ์ ์๋ค.
int n = 10;
auto&& rRef = n;
์์ ๊ฐ์ด lvalue๋ฅผ ๋ฐ๋๋ค๋์ง, ์๋ ์์ ์์ ์ฃผ์์ arg์ฒ๋ผ ์ฌ์ฉ์ด ๊ฐ๋ฅํ ๊ฒ์ด๋ค.
#include <iostream>
#include <mutex>
using namespace std;
void f1(int a) { cout << "f1 : " << a << endl; }
void f2(int& a) { cout << "f2 : " << a << endl; a = 10; }
void f3(int&& a) { cout << "f3 : " << a << endl; }
mutex m;
// arg๋ lvalue, rvalue๊ฐ ๋ชจ๋ ๊ฐ๋ฅํ๋ค
template<typename F, typename A> void lockAndCall(F func, A&& arg)
{
lock_guard<mutex> lock(m);
func(forward<A&&>(arg)); // perfect forwarding
}
int main()
{
int n = 0;
lockAndCall(f1, 10);
lockAndCall(f2, n);
lockAndCall(f3, 10);
return 0;
}
์ ์์ ๋ perfect forwarding
์ ๋ํ ์์ ์ด๊ธฐ๋ ํ๋ฐ, ์ธ์๋ก rvalue reference๋ฅผ ๋ฐ๋ ํจ์์์ ๋ฐ์ ์ธ์๋ฅผ ๋ค๋ฅธ ํจ์์๊ฒ rvalue๋ก ์ ๋ฌํ๋ ๊ฒ์ ์๋ฏธํ๋ค.
template<typename F, typename A> void lockAndCall(F func, A&& arg)
{
lock_guard<mutex> lock(m);
func(arg); // why not?
}
์ด๋ฏธ arg๊ฐ A&& ํ์ ์ธ๋ฐ func์๊ฒ ๊ทธ๋๋ก ์ ๋ฌํ๋ฉด ์๋๋? ๋ผ๊ณ ์๊ฐํ ์ ์์ง๋ง, ๊ธฐ์ตํด์ผ ํ๋ค.
์ด๋ฆ์ด ์๋ rvalue reference๋ lvalue์ด๋ค.
arg๋ ์ด๋ฆ์ด ์๋ ๋งค๊ฐ๋ณ์์ด๊ธฐ ๋๋ฌธ์ lvalue๋ก ์ธ์๋๋ค.