C++복습

C++복습) Modern C++/ 오른값 참조( rvalue)와 std::move

PJNull 2021. 12. 29.
728x90
반응형

오른값 참조는 일반적인 콘텐츠나 코드에서는 자주 활용할 일은 적으나 Modern C++11에서 가장 핵심적인 변화이며 꽃이라고 알려져 있다.

왼값(Lvalue)/오른값(Rvalue)

  • 왼값(Lvalue):단일식을 넘어서 계속 지속되는 개체
  • 오른값(Rvalue):왼값(Lvalue)가 아닌 나머지 값들(임시 값, 열거형, 람다, i++등등..)
int a=3;
a=4;
3=a;	//Error
(a++)=5; //Error

이런 식으로 우리가 사용해왔던 변수들이나 지속가능한 개체들은 왼값이고, 나머지는 오른값으로 되어서 지속되지않는 것을 알 수 있다.

class Admin
{
public:
public:
 int _pass:101;
};

void Test_Copy(Admin admin){}  //복사연산이며 원본과는 관계없다.
void Test_LvalueRef(Admin& admin){} //왼값 참조이며 참조이기에 수정하면 원본에 지장이간다.
void Test_LvalueRef(const Admin& admin){}
int main()
{
 Admin admin;
 Test_Copy(admin);
 Test_LvalueRef(admin);
 Test_LvalueRef(Admin());//Admin의 생성자는 임시값이기에 const가 아니면 에러가 난다.
}

위의 코드와 같은것들이 왼값의 예이다. Admin의 생성자와 같은 임시값은 문법적으로 막혀있는데, 그 이유는 임시적인 값이기에 수정및 제어를 하는것이 불필요하기 때문이다. 단, const를 붙여서 읽기만 하는것은 가능하다.

class Admin
{
public:
public:
 int _pass:101;
};

void Test_RvalueRef(Admin&& admin){}

int main()
{
 Admin admin;
 Test_RvalueRef(admin)//Error 왼값은 받지 못함
 Test_RvalueRef(static_cast<Admin&&>(admin));
 }

위 코드와 같이 &&를 붙이면 오른값참조가 된다. 오른값 참조가 될 경우 왼값은 더이상 인자로 받을수 없으며, 왼값을 받고 싶다면 오른값으로 캐스팅해주어야 되며 원본 수정도 가능하다.

어셈블리의 시선에서는 복사연산/왼값참조/오른값참조는 서로 매우 유사한 방식으로 동작하지만 C++문법 입장에서는 매우 다른 의미를 가진다.

 

  • void Test_Copy(Admin admin):원본을 다른 메모리에 복사하는 것으로 원본을 단순히 복사한 개념.
  • void Test_LvalueRef(Admin& admin):원본을 넘겨줌으로써 수정/제어를 할수 있음.
  • void Test_LvalueRef(const Admin& admin):원본을 넘겨주었지만 수정/제어가 불가하며 읽기만 가능함.
  • void Test_RvalueRef(Admin&& admin): 원본을 넘겨주면서 더이상 활용하지 않을 예정이여서 이동대상이라는 것을 의미한다. 즉, 원본유지를 하지 않아도 된다는 것을 의미한다.

※주의) Admin&& a2=static_cast<Admin&&>(admin)와 같은 경우 a2가 오른값 참조타입(오른값을 저장)이지만 a2자체는 왼값이다.

이동생성자와 이동대입연산자

 

 

이동대입연산자

void operator=(Admin&& admin)
{
 _pass=admin._pass;
 _data=admin._data;
 admin._data=nullptr;
 
}//이동 대입 연산자

이동 대입 연산자의 경우 포인터에 대한 얕은 복사를 행하여도 문제가 되지 않는다. 보통 얕은 복사를 하면 포인터 중복등의 문제로 인해 깊은 복사를 해야되지만 이동대입연산자의 경우 원본의 유지 여부를 묻지 않기 때문에 이러한 이점이 있다.

이동생성자

class Admin
{
 int _pass=101;
 Data* _data=nullptr;
};

Admin(Admin&& admin)
{
 cout<<"이동생성자";
}//이동생성자

이동 대입 연산자와 동일하게 얕은 복사가 일어나며 소유권을 이전하는 생성자이다.

std::move

Admin a1;
Admin a2;

a2=static_cast<Admin&&>(a1);
a2=std::move(a1);//위와 같은 의미

이름에 혼동이 될수 있으나, 이동을 수행하지 않고 받은 인자를 오른값(Rvalue)으로 캐스팅해주는 역할을 한다.

728x90
반응형

'C++복습' 카테고리의 다른 글

C++복습) Modern C++/lambda  (0) 2021.12.30
C++복습) Modern C++/전달 참조  (0) 2021.12.30
C++복습) Modern C++/ override , final  (0) 2021.12.28
C++복습) Modern C++/ Delete  (0) 2021.12.26
C++복습) Modern C++/ enum class  (0) 2021.12.24

댓글