
LValue and RValue References (98, 03, 11)
개요
C++에서 모든 표현식(expression)은 "LValue" 또는 "RValue"라는 두 가지 기본 속성 중 하나를 가집니다. 이 둘을 구분하는 것은 함수 오버로딩, 이동 의미론(move semantics), 완벽한 전달(perfect forwarding)과 같은 C++의 고급 기능을 이해하고 효율적인 코드를 작성하는 데 매우 중요합니다.
- LValue (Locator Value): 메모리 상의 위치를 가지며, 이름으로 참조할 수 있는 객체입니다. 등호(=)의 왼쪽에 올 수 있습니다. (예: 변수)
 - RValue (Right Value): 임시적인 값으로, 메모리 상의 특정 위치를 가지고 있지 않습니다. 등호(=)의 오른쪽에만 올 수 있습니다. (예: 리터럴, 함수 반환 값)
 
C++ 버전별 주요 키워드 도입 시기
- C++98/03: LValue 참조 (
&)가 도입되었습니다. - C++11: RValue 참조 (
&&),std::move,std::forward가 도입되어 이동 의미론과 완벽한 전달이 가능해졌습니다. 
내용 설명
1. 값에 의한 전달 (Pass by Value)
void func(int v)- 값을 복사하여 새로운 객체를 생성합니다.
 - 원본 데이터는 절대 수정되지 않습니다.
 - LValue, RValue 모든 타입의 인자를 받을 수 있습니다.
 
2. 비상수 LValue 참조 (Non-const LValue Reference)
void func(int& v)- 객체의 별칭(alias)으로 동작하며, 복사가 발생하지 않습니다.
 - 참조를 통해 원본 객체를 수정할 수 있습니다.
 - 수정 가능한 LValue만 인자로 받을 수 있습니다. (const LValue나 RValue는 전달 불가)
 
3. 상수 LValue 참조 (const LValue Reference)
void func(const int& v)- 비상수 LValue 참조처럼 복사 없이 객체를 참조하지만, 참조를 통해 값을 수정할 수 없습니다.
 - LValue, RValue 모든 타입의 인자를 받을 수 있습니다.
 - RValue를 인자로 받으면, 임시 객체의 생명주기가 참조가 유효한 동안으로 연장됩니다.
 
4. RValue 참조 (RValue Reference)
void func(int&& v)- C++11에서 도입되었으며, 소멸될 예정인 임시 객체(RValue)를 참조합니다.
 - 이동 의미론(Move Semantics)을 구현하는 데 사용되며, 불필요한 복사를 피하고 리소스 소유권을 효율적으로 이전할 수 있습니다.
 
예제 코드
#include <iostream>
// 값에 의한 전달 (Pass by Value)
void copy_by_value(int v) // 입력 전용
{
    std::cout << "copy_by_value: " << v << std::endl;
}
// 상수 값에 의한 전달 (Pass by const Value)
void copy_by_value_const(const int v) // 입력 전용
{
    std::cout << "copy_by_value_const: " << v << std::endl;
}
// 비상수 참조 (Non-const Reference)
void reference(int &v) // 입출력 가능
{
    std::cout << "reference: " << v << std::endl;
    v = v * 2; // 원본 값 수정 가능
}
// 상수 참조 (const Reference)
void const_reference(const int &v) // 입력 전용
{
    std::cout << "const_reference: " << v << std::endl;
    // v = 10; // 컴파일 오류: 상수 참조는 수정 불가
}
int main()
{
    int lvalue = 2;
    const int lvalue_const = 2;
    std::cout << "--- 값에 의한 전달 ---" << std::endl;
    copy_by_value(lvalue);           // OK: LValue 전달
    copy_by_value(lvalue_const);     // OK: const LValue 전달
    copy_by_value(2);                // OK: RValue 전달
    std::cout << "\n--- 상수 값에 의한 전달 ---" << std::endl;
    copy_by_value_const(lvalue);     // OK: LValue 전달
    copy_by_value_const(lvalue_const); // OK: const LValue 전달
    copy_by_value_const(2);          // OK: RValue 전달
    std::cout << "\n--- 비상수 참조 ---" << std::endl;
    reference(lvalue);               // OK: LValue 전달. lvalue는 이제 4가 됨
    // reference(lvalue_const);      // 오류: const LValue는 비상수 참조로 전달 불가
    // reference(2);                 // 오류: RValue는 비상수 참조로 전달 불가
    std::cout << "lvalue after reference call: " << lvalue << std::endl;
    std::cout << "\n--- 상수 참조 ---" << std::endl;
    const_reference(lvalue);         // OK: LValue 전달 (현재 값 4)
    const_reference(lvalue_const);   // OK: const LValue 전달
    const_reference(2);              // OK: RValue 전달 (임시 객체 생성)
    return 0;
}
실행 결과
--- 값에 의한 전달 ---
copy_by_value: 2
copy_by_value: 2
copy_by_value: 2
--- 상수 값에 의한 전달 ---
copy_by_value_const: 2
copy_by_value_const: 2
copy_by_value_const: 2
--- 비상수 참조 ---
reference: 2
lvalue after reference call: 4
--- 상수 참조 ---
const_reference: 4
const_reference: 2
const_reference: 2
활용팁
- 이동 의미론 (Move Semantics): 
std::move를 사용하여 LValue를 RValue처럼 취급하게 만들 수 있습니다. 이를 통해 임시 객체가 아닌 객체의 리소스(예: 동적 할당된 메모리)를 복사 없이 '이동'하여 성능을 향상시킬 수 있습니다.std::vector,std::string,std::unique_ptr와 같은 표준 라이브러리 컨테이너에서 널리 사용됩니다. - 완벽한 전달 (Perfect Forwarding): 
std::forward는 템플릿 함수에서 인자의 값 카테고리(LValue 또는 RValue)를 그대로 유지하면서 다른 함수로 전달할 때 사용됩니다. 이를 통해 불필요한 복사를 방지하고, 팩토리 함수나 래퍼 함수를 효율적으로 작성할 수 있습니다. 
'개발 > C++ (98,03,11,14,17,20,23)' 카테고리의 다른 글
| Modern C++ : perfect forwarding (11) (1) | 2025.08.19 | 
|---|---|
| Modern C++ : rvalue reference summary (11) (2) | 2025.08.18 | 
| Modern C++ : lvalue, rvalue, value category (98, 11) (2) | 2025.08.17 | 
| Modern C++ : rvalue reference (98, 11) (1) | 2025.08.16 | 
| Modern C++ : dynamic heap memory allocation (98, 11, 14) (1) | 2025.08.14 | 
| Modern C++ : pointer and address (98, 11) (3) | 2025.08.13 | 
| Modern C++ : const reference and value semantics (98, 11) (1) | 2025.08.12 | 
| Modern C++ : string vs std::string vs std::array<char, N> (98, 11, 17) (1) | 2025.08.11 |