๐Ÿ’ฃ์ค‘์š”! std::move ๋งŒ๋“ค๊ธฐ - remove_ref : ์–ด๋ ค์›€. move ๊ตฌํ˜„

๋ณด๋ฌผ์ฐฝ๊ณ ยท2023๋…„ 1์›” 2์ผ
0

c++Intermediate ์ฝ”๋“œ๋ˆ„๋ฆฌ

๋ชฉ๋ก ๋ณด๊ธฐ
43/62
post-thumbnail
  • ์ถ”๊ฐ€ 231015
  • remove_reference ์™€ remove_referece_t์˜ ์ฐจ์ด๋Š”
    ์ „์ž๋Š” operator = ์—ฐ์‚ฐ์ž๊ฐ€ ์—†์ง€๋งŒ, ํ›„์ž๋Š” operator= ์—ฐ์‚ฐ์ž๊ฐ€ ์žˆ์Œ.

-> ๊ทผ๋ณต์ ์ธ ์ฐจ์ด์ ์€ remove_referenc_t ๋Š” using ์ฒ˜๋ฆฌ๋  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—
๋ณต์žกํ•˜๊ฒŒ typename์„ ์ž‘์„ฑํ•  ํ•„์š” ์—†๋‹ค.

https://crmerry.tistory.com/113

  • ์‹คํ—˜์— ์‚ฌ์šฉ๋  Test ํด๋ž˜์Šค
class Test
{
public:
    Test() { std::cout << "Constructor" << std::endl; }
    ~Test() { std::cout << "Destructor" << std::endl; }

    Test(const Test& t)
    {
        std::cout << "Copy Constructor" << std::endl;
    }
    Test(Test&& t) noexcept
    {
        std::cout << "Move Constructor" << std::endl;
    }

    Test& operator=(const Test& t)
    {
        std::cout << "Copy =" << std::endl;
        return *this;
    }
    Test& operator=(Test&& t) noexcept
    {
        std::cout << "Move =" << std::endl;
        return *this;
    }
};

remove_ref ์˜ ์ •์˜

: ํ…œํ”Œ๋ฆฟ ํƒ€์ž…์œผ๋กœ ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ํƒ€์ž…์˜ ์ฐธ์กฐ๋ฅผ ์ œ๊ฑฐํ•˜๊ฒ ์Œ!

typename remove_reference::type ์ž๋ฃŒํ˜• ํ™•์ธํ•˜๊ธฐ

  • remove_reference๋กœ lvalue์ธ main::n์˜ ์ฐธ์กฐ๊ฐ€ ์—†์–ด์ง€๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ.

    ์‹คํ—˜
    : 21๋ฒˆ์ค„์€ lvalue ์ด๊ธฐ ๋•Œ๋ฌธ์— rvalue 4 ๋ฐ›์„์ˆ˜ ์—†์Œ.
    : 23๋ฒˆ์ค„์€ rvalue ์ด๊ธฐ ๋•Œ๋ฌธ์— lvalue n์„ ๋ฐ›์„ ์ˆ˜ ์—†์Œ.

move๋ฅผ ์ง์ ‘ ๋งŒ๋“ค์–ด๋ณด์ž!

ํ•ต์‹ฌ!! ๋ฐ˜๋“œ์‹œ ์•Œ์•„์•ผ ํ•œ๋‹ค!!

  • ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค๊ฒƒ์ธ๊ฐ€? ๊ฐ•์ถ”!
  1. ๋ชจ๋“  ํƒ€์ž…์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก template์œผ๋กœ ๋งŒ๋“ค์ž.
  2. move ์ƒ์„ฑ์ž์™€ , move ๋Œ€์ž… ์ดํ›„์—๋Š” rvalue๋กœ ๋ฐ˜ํ™˜ํ•จ. -> ํ•จ์ˆ˜ ๋ฐ˜ํ™˜ํƒ€์ž…์„ T&& ๋กœ ํ•˜์ž.
  3. move์— ์ธ์ž๋กœ ๋“ค์–ด์˜ฌ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ lvalue, rvalue๋ชจ๋‘ ๊ฐ€๋Šฅํ•จ!
    -> ํƒ€์ž… ๋ชจ๋‘ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒŒ forwarding ref ํƒ€์ž…์œผ๋กœ ์„ค์ •ํ•˜์ž.
  4. ์ธ์ž๋กœ ๋“ค์–ด์˜ค๋Š” ์ •๋ณด๋ฅผ rvalue๋กœ ์บ์ŠคํŒ…ํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ.
    -> static_cast<T&&> ๋ฐ˜ํ™˜ ํ•˜์ž.
  5. ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ํ•  ๊ฒฝ์šฐ, lvalue๋Š” ํ…œํ”Œ๋ฆฟ์— ๋“ค์–ด์˜ค๋Š” ์ˆœ๊ฐ„
    ์ง„์ž…ํ•˜๋Š” ๊ณณ์—์„œ ref collapse๋กœ ์ธํ•ด์„œ static_cast<T&> ๋กœ ๊ฒฐ์ •๋œ๋‹ค.
    -> ์ฐธ์กฐ๋ฅผ ์ง€์›Œ์•ผ ํ•œ๋‹ค. remove_reference_t ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ์ฐธ์กฐ ์ง€์šฐ์ž.
  6. ์ฐธ์กฐ์„ฑ์„ ์ง€์› ์œผ๋‹ˆ๊นŒ. ์ด์ œ rvalueํƒ€์ž…์œผ๋กœ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋ฏ€๋กœ.
    -> && ์บ์ŠคํŒ…ํ•˜์ž.
template<typename T>
T&& xmove(T&& _obj)
  {
  	return static_cast<remove_reference_t<T> &&>(_obj));
  
  }

  • 1) template์—์„œ ์ธ์ž์—์„œ ๋ฐ›์„๋•Œ ๋ณต์‚ฌ ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ , rvalue์™€ lvalue๋ฅผ ๋ชจ๋‘ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€
    forwarding reference์ด๊ธฐ ๋•Œ๋ฌธ์— T&&๋กœ template ์ธ์ž ์„ค์ •ํ•˜์ž.
    (์ผ๋ฐ˜ T๋กœ ๋†“์œผ๋ฉด ๋ณต์‚ฌ ๋ฐœ์ƒํ•˜์ž–์•„...)
    -> T&& ๋ฅผ ํ•จ์ˆ˜ ์ธ์ž๋กœ ํ•ด์„œ ๋งŒ๋“ค์ž

  • 2) ๋ฐ˜ํ™˜ ํƒ€์ž…์€ rValue ์ด๋ฏ€๋กœ , T&& ํ˜•์„ ๋ฐ˜ํ™˜ํ•˜์ž.

template <typename T> T&& xmove(T&& obj)
{
	return static_cast<T&&>(obj)
}

int main()
{
	Test t1;
    Test t2 = t1; // => copy
    Test t3 = xmove(t1); // => move ํ–ˆ๋Š”๋ฐ๋„ copy ๋‚˜์˜ด. 
	Test t4 = xmove(Test()); // => move
}
  • but, ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด lvalue๋ฅผ ๋„ฃ์œผ๋ฉด ๋ฌธ์ œ์ž„.
Object a;
Object b = xmove(a);
  • ์ด์œ 
    : ์™œ๋ƒํ•˜๋ฉด T&& ์— T์—๋‹ค๊ฐ€ lvalue์ธ a๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด,
    T&& & => T& ๊ฐ€ ๋˜๊ธฐ ๋•Œ๋ฌธ์ž„.
    ์บ์ŠคํŒ…ํ•˜๋Š” ๊ณณ์ด lvalue ์ฐธ์กฐ๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ•จ.

    ์œ„์—์„œ ๋ฐœ์ƒํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์ž.

  • ๋ฌธ์ œ 1๋ฒˆ : lValue๊ฐ€ ์ธ์ž๋กœ ๋“ค์–ด์˜ค๋ฉด, ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.
    ํ•ด๊ฒฐ์ฑ…
    - 1) ์ธ์ž๋กœ ๋“ค์–ด์˜ค๋Š” T์˜ ์ฐธ์กฐ๋ฅผ ์ œ๊ฑฐํ•˜๋Š”
    remove_reference๋ฅผ ์‚ฌ์šฉํ•˜์ž.
    - 2) : ์ฐธ์กฐ๋ฅผ ์ œ๊ฑฐํ•œ ํ›„์— &&๋ฅผ ๋ถ™์ด์ž
    • 3) ๋ฐ˜ํ™˜ ํƒ€์ž…๋„ rValue๋กœ ์ž‘์„ฑํ•˜์ž.
template <typename T> T&& xmove(T&& obj)
{
	return static_cast<remove_reference<T>::type &&>(obj);
    
}
  • ์˜๋ฏธ

    <remove_reference < T >::type &&>
    // T ํƒ€์ž…์ด ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ์ œ๊ฑฐํ•˜๊ณ , &&๋ฅผ ๋ถ™์ด๊ฒ ๋‹ค๋Š” ์˜๋ฏธ์ž„.

  • ๋ฐ˜ํ™˜๊ฐ’
    : ๊ทธ๋Ÿฐ๋ฐ ๋ฐ˜ํ™˜๊ฐ’์— ๋Œ€ํ•ด์„œ ์ƒ๊ฐ์„ ํ•ด๋ณด๋ฉด, ํ…œํ”Œ๋ฆฟ ์ธ์ž T๊ฐ€ ๋ฐ˜ํ™˜ํƒ€์ž…์ธ
    T&& ์— ์˜ํ•ด ๋ ˆํผ๋Ÿฐ์Šค ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•œ๋‹ค.
    -> ๋ฐ˜ํ™˜๊ฐ’๋„ remove_reference_t ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์•ผ ํ•œ๋‹ค.
template <typename T> T&& xmove(T&& obj)
{
	return static_cast<typename remove_reference<T>::type &&>(obj);
}
  • ์•„๋ž˜์˜ ์ตœ์ข…์ฝ”๋“œ๊ฐ€ ๋ฐ”๋กœ ์ง„์ •ํ•œ move ๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.
    ๊ทธ๋Ÿฐ๋ฐ ๋„ˆ๋ฌด ๋ณต์žกํ•ด template::type ์ฒ˜๋ฆฌ
    ํ•œ๋ฒˆ ๋” ์ˆ˜์ •ํ•˜์ž...
template <typename T> typename remove_reference<T>::type&& xmove(T&& obj)
{
	return static_cast<typename remove_reference<T>::type &&>(obj);
}

์ค‘์š”!! ์ตœ์ข… ๊ตฌํ˜„

  • typename ์‚ฌ์šฉํ•˜๊ธฐ ์‹ซ์–ด์„œ ์ด๋ ‡๊ฒŒ ์ฒ˜๋ฆฌํ•จ.
template <typename T> remove_reference_t<T>&& xmove(T&& obj)
{
	return static_cast<remove_reference_t<T> &&>(obj);
}
  • ์‹ค์ œ move๊ฐ€ ๊ตฌํ˜„๋œ ์ฝ”๋“œ

๊ฒฐ๋ก 

: ์ด์ „ ํฌ์ŠคํŠธ์—์„œ move๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด lvalue ์ด๋”๋ผ๋„ ravlue๋กœ ์บ์ŠคํŒ…๋œ๋‹ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋Š”๋ฐ, ์ง€๊ธˆ์˜ ํฌ์ŠคํŠธ์—์„œ ์ด๋Ÿฌํ•œ ์ด์œ ๋ฅผ ์•Œ์ˆ˜ ์žˆ๋‹ค.

  • lvalue์ด๋“  , rvalue ์ด๋“  ์ฐธ์กฐ๋ฅผ ์ง€์šด ํ›„์—... rvalue๋กœ ์บ์ŠคํŒ…์„ ํ•ด๋ฒ„๋ฆฐ๋‹ค!
profile
๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅ

0๊ฐœ์˜ ๋Œ“๊ธ€