초보 게임 클라이언트
article thumbnail
Published 2023. 3. 17. 18:58
Value Categories C++

Value Categories

  • Value Categories는 연산자 오버로딩, 포인터 등과 같은 C++의 언어적 기능이라기 보다는 컴파일러가 C++의 표현식(Expression)을 이해하고 해석하는 과정 중 한 부분이다.
  • Value Categories를 이해하면
    • 이해하기 전에는 난해했던 에러 메시지를 효과적으로 해석할 수 있다.
    •  C++의 언어적 기능인 연산자와 reference가 어떻게 동작하는지에 대한 통찰력을 기를 수 있다.

진화한 LValue와 RValue

초기의 Value Categories에는 C에서 소개되었던 lvalue와 rvalue 두 가지가 있었고, 이들은 비교적 간단명료한 개념들이었다. 하지만 C++과 함께 class, const 그리고 reference가 등장하면서 이러한 기능들에 대응하기 위해 이 개념들은 진화해야했고 복잡해졌다. 얼마 후에 rvalue reference가 추가된 Modern C++이 등장하면서 기존의 개념들은 더욱더 복잡해졌고, 두 가지만 존재하던 Value Categories에 새로운 요소들이 추가되었다.

Object

메모리 상의 정해진 위치에 존재하는 것들을 Object라고 하고 이름을 가지고 있는 오브젝트를 변수(Variable)라 한다. 이 이름은 오브젝트 그 자체인 것처럼 사용된다. 모든 오브젝트가 이름을 가지고 있지는 않다. 이름을 가지고 있지 않은 오브젝트들은 포인터로 관리한다.

/*
 * Object: 메모리에 저장된 5
 * 변수: x
*/
int x = 5;

/* x를 5인 것처럼 사용한다 */
int y = x + 77;

Lvalues

Lvalue는 메모리에 존재하는 오브젝트의 주소를 참조(Evaluate)할 수 있는 식이다. 예로는 변수(const 변수 포함), 역참조 된 포인터, 배열의 요소, 클래스 멤버와 Lvalue를 반환하는 함수 또는 조건부 연산자(Conditional Operator)가 있다. Lefthand/Left value라고 불리는데 대입 연산자(=)의 왼편에 위치해서 리터럴(Rvalue) 또는 다른 변수에 저장된 값을 대입할 수 있기 때문이다.

/* x는 Lvalue */
int x = 12;

/* 오류! 대입 연산자의 왼편은 항상 Lvalue여야 한다 */
97 = x;

Rvalues

Rvalue는 메모리에 존재하는 오브젝트의 주소를 참조(Evaluate) 하지 않는 식이다. Lvalue가 아닌 것은 Rvalue이다. 예로는 리터럴, 리터럴을 반환하는 식 또는 함수가 있다. Righthand/Right value라고 불리는데 대입 연산자(=)의 오른편에 위치해서 변수 또는 Lvalue를 초기화할 때 사용되기 때문이다.

/* 12는 Rvalue */
int x = 12; 

/* (x + 8)은 리터럴을 반환하기 때문에 Rvalue */
int y = x + 8;

L-Value 레퍼런스

L-Value 레퍼런스는 L-Value를 참조한다. & 연산자를 사용한다.

int main()
{
    int x = 5;
    int& lval_Ref = x;
    return 0;
}

R-Value 레퍼런스

R-Value 레퍼런스는 R-Value(임시적인 오브젝트)를 참조한다. && 연산자를 사용한다.

int main()
{
    int& x = 100; // *오류* R-Value 100의 L-Value 레퍼런스 x
    int&& y = 5; // R-Value 5의 R-Value 레퍼런스 y
    int z = 97;
    int&& p = z; // *오류* L-Value z의 R-Value 레퍼런스 p
    return 0;
}

L-Value 레퍼런스를 매개변수로 하는 함수를 오버로딩하여 R-Value 레퍼런스를 매개변수로 하는 함수를 정의할 수 있다.

#include <iostream>
using namespace std;

// L-Value 레퍼런스를 매개변수로 하는 PrintInt 함수
void PrintInt(const int& x)
{
    cout << x << endl;
}

// R-Value 레퍼런스를 매개변수로 하는 PrintInt 함수(오버로딩)
void PrintInt(const int&& x)
{
    cout << x << endl;
}

int main()
{
    int A = 7;
    
    PrintInt(A);
    PrintInt(75);
    return 0;
}
profile

초보 게임 클라이언트

@앵춘

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그