'C++' Rvalue Reference

토스트·2025년 1월 6일

'C++' basic

목록 보기
11/35

좌측값(Lvalue) VS 우측값(Rvalue)

좌측값 : 메모리 주소를 가지는 객체로 프로그램의 다른 위치에서 참조하거나 수정할 수 있는 값입니다.
ex) int x = 10;에서 'x'나 int w = x + y;에서 'w', 'x', 'y'는 좌측값입니다.

우측값 : 일시적인 값으로, 메모리 주소를 가지지 않으며 대개 함수 반환값이나 리터럴 값입니다.
ex) int x = 10;에서 '10'이나 int w = x + y;에서 'x + y'가 우측값입니다.

좌측값 참조와 우측값 참조

int x = 5, int y = 10;
int & l = x; // Lvalue Refernce

int&& r1 = 5; // Rvalue Reference
int&& r2 = x + y; // Rvalue Reference

우측값 참조(Rvalue Reference)

&& 연산자를 사용하여 우측 값(Rvalue)을 참조하는 방식입니다.

우측값 참조 도입으로 해결하고자 한 문제점
이전 C++에서는 객체를 전달하거나 반환할 때, 복사 생성자를 통해 데이터를 복사해야 했습니다. 이 과정은 큰 데이터 구조에서 비용이 많이 들었고, 복사가 반복되면 성능이 급격히 저하되었습니다.
또한, 임시 객체를 사용하려면 항상 복사가 필요했는데, 임시 객체는 값이 금방 사라지기 때문에 복사 비용이 불필요하게 발생했습니다.

이와 같은 복사 비용 문제를 해결하고 임시 객체를 효율적으로 처리하기 위해 우측값 참조가 도입되었습니다. 이를 통해 복사 없이 리소스를 이동할 수 있게 되어, 성능을 최적화하고 불필요한 메모리 할당을 피할 수 있게 되었습니다.

유니버셜 참조(Universal Reference)

유니버셜 참조는 템플릿에서 사용되는 T&&로, r-value와 l-value를 모두 처리할 수 있습니다.

가벼운 예시

template<typename T>
void foo1(T&& arg) { } // arg는 유니버셜 참조입니다.

void foo2(int&& num) { } // num은 우측값 참조입니다. 

이동 의미론(Move Semantics)

객체를 복사하지 않고 자원의 소유권을 이동시키는 방식입니다. 객체가 더 이상 필요하지 않은 자원을 다른 객체로 이동할 수 있게 해 줍니다. 이를 통해 불필요한 복사를 피하고, 성능을 크게 향상시킬 수 있습니다.

  • 이동 생성자(Move Constructor) : 객체가 새로 생성될 떄, 다른 객체의 자원을 이동하여 새 객체에 할당하는 생성자입니다.
  • 이동 대입 연산자(Move Assignment Operator) : 이미 존재하는 객체에 다른 객체의 자원을 이동하는 연산자입니다.

둘 모두 std::move 함수를 통해 구현됩니다.

완전 전달(Perfect Forwarding)

인자의 값 카테고리(lvalue 또는 rvalue)를 손실 없이 그대로 전달하는 것입니다.
우측값으로 전달된 인자는 다른 함수에서 우측값으로 그대로 전달되어야 하며, 좌측값으로 전달된 인자는 다른 함수에 좌측값으로 전달되어야 합니다.

std::forward 함수는 유니버셜 참조로 전달된 인자에 대해 값 카테고리를 그대로 유지하면서 다른 함수에 전달할 수 있도록 도와주는 함수입니다. 이 함수는 주로 템플릿 함수에서 인자의 값을 전달할 때 사용됩니다.

0개의 댓글