Program Language/C & C++

[C++] values

야곰야곰+책벌레 2021. 10. 8. 11:36
728x90
반응형

C에서의 Rvalue, Lvalue는 좌측 값은 대입(assignment) 시에 왼쪽 혹은 오른쪽에 오는 식(expression)이고, 우측 값은 대입 시에 오직 오른쪽에만 오는 식이다.라고 정의하고 있지만 C++에서는 다음과 같이 정의하고 있다.

좌측 값은 어떠한 메모리 위치를 가리키는데, & 연산자를 통해 그 위치를 참조할 수 있다.
우측 값은 좌측 값이 아닌 값들이다.

C++11부터는 prvalue, xvalue, glvalue가 추가되었다.

C++11에서는 이러한 value들을 다음과 같이 나누었다.

lvalue : identity를 가지면서 move 될 수 없는 표현식

xvalue : identity를 가지면서 move 될 수 있는 표현식

prvalue : identity를 가지지 않고 있으면서 move 될 수 있는 표현식들

glvalue : identity를 가지고 있는 표현식들(lvalue, xvlaue 모두 glvalue 표현식)

rvalue : move 될 수 있는 표현식들(prvalue, xvalue 모두 rvalue 표현식) 

identity를 가지고 있지 않으면서 move 될 수 없는 것들.

identity를 가진다 : 값이 식별성을 가지고 있다.
move 될 수 있다 : 값이 메모리에서 이동될 수 있다. 포인터가 있는 값은 주소를 이동할 수 있다.

move는 메모리 주소는 유지되면서 포인터만 변경, copy는 값을 복사하기 때문에 매번 메모리가 할당된다.


lvalue ( identity를 가지면서 move 될 수 없는 값들 )

  • 대입문의 좌측에 올 수 있다.
  • &연산자로 값의 주소를 얻어올 수 있다.
  • 표현식이 끝나더라도 값이 살아 있다.
static int a = 10;
int& inc()
{
	a++;
	return a;
}

int get()
{
	return a;
}

int main()
{
	int a = 10, b = 10, c = 10;
	int *j = &a; // 참조 가능하기 때문에 a는 lvalue
	inc() = 43; // inc()는 lvalue
	int* ptr = &inc(); // &inc()는 가능하기 때문에 lvalue
	++a; // a는 lvalue
	int C[4];
	cout << C[1] << endl; // c[1]도 lavlue
	a ? b : c;  // 반환 값은 b or c 이므로 lvalue
	
	return 0;
}

xvalue ( identity를 가지면서 move 될 수 있는 표현식들 )

  • 컴파일러만 사용하는 객체이기 때문에 &연산자가 허용되지 않는다.
  • 표현식이 끝났을 때 사라진다.

컴파일러가 필요로 하는 임시 데이터 저장 공간을 xvlaue라고 한다. std::move()와 같이 rvalue reference를 리턴할 수 있는 함수는 lvalue를 move 하고, move 한 값은 xvalue에 속하게 된다. 

prvalue ( identity를 가지고 있지 않으면서 move 될 수 있는 표현식들 )

  • 대입문의 우측에 올 수 있다.
  • 주소가 없다.

prvalue는 pure_rvalue의 약자로 후위 증감 연산자, 문자열 리터럴을 제외한 모든 리터럴 등이 prvalue에 속한다.

int a = 10;
int b = 20;
if (a < b) // a < b의 결과 값 bool은 prvalue
{

}

glvalue ( identity를 가지고 있는 표현식들. lvalue, xvalue )

glvalue는 xvalue 혹은 lvalue를 의미한다. 쉽게 말하자면 데이터를 저장할 수 있는 메모리의 위치 정보를 가지고 있다. gvalue는 lvalue에서 rvalue로 변환이 가능한데 포인터, 배열 및 함수에서 암시적 변환을 통해 prvalue로 변환할 수 있다.

rvalue ( move 될 수 있는 표현식들. prvalue, xvalue )

rvalue는 메모리 주소에서 이동이 될 수 있는 표현식들을 통칭하는 말이다. 

int& inc1(int &a)
{
	a++;
	return a;
}

int intc2(int& a)
{
	a++;
	return a;
}

inc1() 함수는 int&를 리턴하게 되는데 이는 a라는 실제 객체를 리턴 시키는 함수이며 lvalue 속성을 갖는다.

inc2() 함수는 int를 리턴하게 되는데 이는 a의 복제본을 리턴하는 것이며 rvalue로 변환된다.

728x90
반응형

'Program Language > C & C++' 카테고리의 다른 글

error C2558 : no copy constructor available or copy constructor is declared 'explicit'  (4) 2021.10.21
[C++] std::async  (0) 2021.10.19
[C++] std::move  (0) 2021.10.08
[C++] packaged_task  (2) 2021.10.07
[C++] thread_local  (0) 2021.10.07