WinAPI

RValue,LValue reference

Nin 2021. 1. 14. 02:39
int A = 100;

A가 LValue 100이 RValue 이다.

LValue란

메모리 위치를 가지고 있고 const가 아닌것을 말한다.

RValue란 상수, 임시 객체(이름이 없는)를 말한다.

#include <iostream>

class Test
{
public:
   int* Ptr;
   
public:
   Test()
   {
      std::cout << "생성자" << std::endl;
      Ptr = new int[100];
   }
   
   Test(const Test& _Other)
   {
      std::cout << "복사 생성자" << std::endl;
      Ptr = new int[100]; // 깊은복사      
   }
   
   ~Test()
   {
      std::cout << "소멸자" << std::endl;
      if(Ptr !=nullptr)
      {
         delete Ptr;
         Ptr = nullptr;
      }
   }

};

복습)

만약 깊은 복사가 아닌 Ptr = _Other.Ptr;

이렇게 얕은 복사를 해줄경우 똑같은 곳을 두번 delete 하기 때문에

프로그램이 터진다.


int main()
{
   Test NewTest = Test();
}

이 코드를 실행하면 "생성자" , "소멸자"가 한번씩 출력된다.

int main()
{
   Test NewTest = Test();
   Test NewTest2 = NewTest;
}

이렇게 실행하면

"생성자"

"복사생성자"

"소멸자"

"소멸자"

이렇게 출력된다.


Test TestCreate()
{
   Test NewTest = Test();
   return NewTest;
}

int main()
{
   Test NewTest3 = TestCreate();
}

위의 함수를 추가하고 동작 원리를 생각해보면

우선 Test() 생성자로 들어가서 int 100개가 할당된다.그러고 return 되면서

복사생성자로 들어간다.복사생성자에서 또 int 100개를 할당한다.

그리고 나서 소멸자로 들어가서 100개가 지워진다.

여기서 문제점은 int를 200개 할당했다는 거다.

외부에 복사해주려고 int 100개를 한번더 할당하고 사라진다.

"생성자"

"복사생성자"

"소멸자"

"소멸자"

이렇게 출력되며 이를 RVO 라고 하는데 Release 에서는 최적화가 된다.

Release 모드로 실행시 알아서 최적화가 되어서

"생성자"

"소멸자"

Test TestCreate()
{
   return Test();
}

이렇게 꼬리 형식으로 바꿔주면 Debug모드에서도 

"생성자"

"소멸자"

이렇게 출력되고 이를 NRVO라고 한다.

이름 없는 리턴으로 의도적으로 최적화를 일으키는것을 말한다.


#include <iostream>
class Test
{
public:
   int* Ptr;
   
public:
    Test(const Test&& _Other)
   {
      std::cout << "RValue 복사 생성자" << std::endl;
      Ptr = _Other.Ptr;   
      _Other.Ptr = nullptr;
   }
   
   Test(const Test& _Other)
   {
      std::cout << "복사 생성자" << std::endl;
      Ptr = new int[100]; // 깊은복사      
   }
};

Test TestCreate()
{
   Test NewTest = Test();
   return NewTest;
}

int main()
{
   Test NewTest3 = TestCreate();
}

그래서 위의 코드의 Test(const Test&& _Other) 이러한 문법이 있고 

이 코드의 실행은 TestCreate 함수에서 리턴될때 

Test(const Test&& _Other) 이쪽으로 들어가고 이를 RValue reference 라고 한다.

TestCreate함수에서 리턴된 값은 이름이 없다.(파괴되고 사라지는 값)

굳이 깊은 복사로 새로운 할당을 하는것이 아닌 얕은복사(대입)로 처리한다.