본문 바로가기

카테고리 없음

l-value, r-value in C++

C++에서 l-value(left value)와 r-value(right value)는 변수나 표현식이 메모리에서 차지하는 위치 및 이동 가능성에 따라 구분됩니다.


l-value (좌측 값)

  • 메모리에 저장된 값으로, 식의 왼쪽과 오른쪽에서 모두 사용 가능
  • 변경 가능하며, 주소를 참조할 수 있음 (& 연산자로 주소를 얻을 수 있음)
  • 변수, 참조 변수, 배열 요소, 객체 등이 해당

 

int x = 10;  // 'x'는 l-value (메모리에 저장됨)
x = 20;      // 좌항(l-value)인 'x'에 20을 할당 (가능)
int &ref = x; // 참조 가능 (l-value reference)

 

l-value 특징

  • 식의 왼쪽(할당 대상)과 오른쪽(값 제공)에서 모두 사용 가능
  • 참조(&)를 통해 l-value reference 생성 가능

r-value (우측 값)

  • 임시로 생성되는 값으로, l-value가 될 수 없는 값
  • 할당 연산자의 오른쪽에서만 사용 가능
  • 값이 있지만 주소를 가지지 않음 (& 연산자로 주소를 얻을 수 없음)
  • 리터럴, 연산 결과, 임시 객체 등이 해당
int y = 5;   // 'y'는 l-value
y = 10 + 20; // '10 + 20'은 r-value (연산 결과)

int &&r = 10; // r-value reference (C++11부터 가능)

 

r-value 특징

  • 메모리에 직접 저장되지 않는 임시 값
  • 참조할 수 없지만, r-value reference (&&) 를 통해 참조 가능 (C++11 이상)

l-value와 r-value의 주요 차이점

구분 l-value r-value
메모리 저장됨 저장되지 않음 (임시값)
주소 참조 가능 (&) 불가능 (&)
사용 위치 식의 좌/우 모두 가능 식의 우측에서만 사용 가능
참조 int &ref = x; 가능 int &&r = 10; 가능 (C++11)

r-value reference (&&) (C++11)

C++11부터 r-value reference(&&)가 도입되어, r-value를 참조할 수 있게 되었습니다.

 

int &&rr = 10; // '10'은 r-value, r-value reference로 참조 가능
std::cout << rr << std::endl; // 10 출력

 

r-value reference의 주요 용도

  1. Move Semantics (이동 시멘틱)
    • 불필요한 복사를 줄이고, 효율적인 리소스 이동 가능
  2. Perfect Forwarding (완벽한 전달)
    • 템플릿에서 매개변수를 원래 타입 그대로 전달 가능

Move Semantics 예제

#include <iostream>
#include <vector>

class MoveExample {
public:
    std::vector<int> data;

    MoveExample(std::vector<int>&& d) : data(std::move(d)) { // r-value reference 사용
        std::cout << "Move Constructor Called" << std::endl;
    }
};

int main() {
    std::vector<int> v = {1, 2, 3};
    MoveExample obj(std::move(v)); // v의 데이터를 obj로 이동
}

🔹 std::move(v)를 사용하여 불필요한 복사를 방지하고, 리소스를 효율적으로 이동

 

Perfect Forwarding 예제

#include <iostream>
#include <utility>

void process(int& x) { std::cout << "L-value reference" << std::endl; }
void process(int&& x) { std::cout << "R-value reference" << std::endl; }

template<typename T>
void forward_example(T&& arg) {
    process(std::forward<T>(arg));
}

int main() {
    int a = 10;
    forward_example(a);  // L-value reference
    forward_example(20); // R-value reference
}

🔹 std::forward<T>(arg)를 사용하여 원래의 타입을 유지하며 전달


Q&A

Q: l-value와 r-value의 차이점은 무엇인가요?

 A: l-value는 메모리에 저장된 값으로 참조가 가능하며, 식의 좌/우에서 사용할 수 있습니다. 반면 r-value는 임시 값으로, 주소를 가질 수 없고 식의 우측에서만 사용됩니다.

Q: r-value reference(&&)는 언제 사용하나요?

A: r-value reference는 주로 Move Semantics(이동 시멘틱)과 Perfect Forwarding(완벽한 전달)에서 사용됩니다. 이를 통해 불필요한 복사를 줄이고, 성능을 최적화할 수 있습니다.

Q: std::move는 무엇인가요?

A: std::move는 l-value를 r-value로 변환하는 함수로, 이동 시멘틱을 활용할 때 사용됩니다. 이를 통해 객체의 소유권을 이전하고, 불필요한 복사를 방지할 수 있습니다.


정리

  • l-value → 메모리에 저장된 값, 참조 가능, 식의 좌/우 사용 가능
  • r-value → 임시 값, 주소 없음, 식의 우측에서만 사용 가능
  • r-value reference (&&) → C++11 이후 도입, Move Semantics 활용 가능

이해를 돕기 위해 요약하면,
l-value"메모리에 저장된 값"
r-value"일시적인 값"
✅ **r-value reference (&&)**는 "임시값을 참조하기 위한 도구"