SW개발/C++

L-value와 R-value

코코도롱 2025. 2. 28. 16:35
반응형

C++에서 L-valueR-value는 프로그램에서 변수와 표현식의 메모리 속성과 수명에 관련된 중요한 개념입니다. 이를 이해하면 메모리 할당, 최적화, 참조자와 이동자의 작동 방식을 명확히 알 수 있습니다.

정리

  • L-value: 메모리에 저장되는 영속적인 객체
  • R-value: 임시로 생성되어 연산이 끝나면 사라지는 값
  • C++11부터는 R-value 참조와 Move Semantics를 활용하여 성능 최적화가 가능함

1. L-value와 R-value의 정의

L-value

  • **L-value (Left Value)**는 특정 메모리 주소에 저장된 객체입니다.
  • 표현식이 끝난 후에도 사라지지 않고 메모리에 남아 있는 값입니다.
  • 변수와 같이 이름을 가진 객체가 대표적인 L-value입니다.
  • L-value는 할당 연산자의 왼쪽 피연산자가 될 수 있습니다.

예시:

int x = 10;  // x는 L-value
x = 20;      // 할당 연산자의 왼쪽에 위치

R-value

  • **R-value (Right Value)**는 특정 메모리 주소에 저장되지 않은 임시 값입니다.
  • 표현식이 끝나면 사라지는 임시적인 데이터입니다.
  • 숫자 상수, 연산 결과 등이 대표적인 R-value입니다.
  • R-value는 할당 연산자의 오른쪽 피연산자가 될 수 있습니다.

예시:

int y = 5 + 3;  // 5 + 3은 R-value (임시 값 8)

2. L-value와 R-value의 메모리 관점

메모리 저장 방식

  • L-value: 메모리 상의 특정 주소에 저장되며, 해당 주소는 참조 연산자 &를 통해 접근할 수 있습니다.
  • R-value: CPU 레지스터 또는 임시 메모리에 저장되며, 참조 연산자를 사용할 수 없습니다.

예시:

int a = 10;      // a는 L-value
int* ptr = &a;   // L-value의 주소 참조 가능
int* ptr2 = &10; // 오류! R-value는 주소가 없음

오버헤드 측면

  • L-value: 메모리에 저장되어 필요할 때 참조가 가능하여 재사용에 유리합니다.
  • R-value: 임시 메모리에 저장되므로 수명이 짧고, 연산이 끝나면 제거됩니다.

3. L-value와 R-value의 함수 반환 값

L-value 반환 함수

L-value를 반환하는 함수는 참조자를 반환합니다.

int global = 100;
int& getGlobal() {
    return global;  // L-value 반환
}

getGlobal() = 400;  // L-value이므로 할당 가능

R-value 반환 함수

R-value를 반환하는 함수는 임시 값을 반환합니다.

int getValue() {
    return 100;  // R-value 반환
}

getValue() = 400;  // 오류! R-value에는 할당 불가

4. L-value 참조와 R-value 참조

L-value 참조

int x = 10;
int& ref = x;  // L-value 참조
ref++;         // x의 값이 증가됨

R-value 참조 (C++11 이상)

  • C++11부터는 && 키워드를 사용하여 R-value 참조를 도입했습니다.
  • 이동语(move semantics)를 통해 불필요한 복사를 방지하고 성능을 최적화합니다.
int&& rref = 10;  // R-value 참조

5. R-value 참조와 Move Semantics

Move Semantics는 객체의 리소스를 복사하지 않고 소유권을 이전하는 기술입니다.

예시:

#include<iostream>
#include<vector>
#include<utility>

int main() {
    std::vector<int> v1{1, 2, 3};
    std::vector<int> v2 = std::move(v1);

    std::cout << "v1 size: " << v1.size() << std::endl;
    std::cout << "v2 size: " << v2.size() << std::endl;
}

출력:

v1 size: 0
v2 size: 3
반응형