Value Category

하루공부·2024년 1월 20일
0

C++

목록 보기
17/25
post-thumbnail

C++ 아이콘 제작자: Darius Dan - Flaticon


value category

  • C++의 모든 식은 타입과 값 카테고리를 가진다. 아래를 기준을 하여 5개가 있다.

    • 정체를 알 수 있는가?
    정체를 알 수 있다는 말은 해당 식이 어떤 다른 식과 같은 것인지 아닌지 를 구분할 수 있다는 말
    일반적인 변수라면 주소값을 취해서 구분할 수 있겠고 함수의 경우라면 그냥 이름만 확인해보면 됨

    • 이동 시킬 수 있는가?
    해당 식을 다른 곳으로 안전하게 이동할 수 있는지?
    즉 해당 식을 받는 이동 생성자, 이동 대입 연산자 등을 사용할 수 있어야만 한다.

이동 가능(rvalue)이동 불가능
정체를 알 수 있다(glvalue)xvaluelvalue
정체를 알 수 없다prvalue쓸모 없음

(pure rvalue) 순수 우측값
(eXpiring value) 소멸하는 값
(generalized lvalue) 일반화된 좌측값


lvalue

  • lvalue는 무조건 왼쪽에 오며, 무조건 주소값을 가진다(&) ex) int i, &i

int* pi = &i 에서는 pi는 lvalue로 i의 주소를 가지지만 다른 곳에서 rvalue로 값을 가져올 수 있다.

여기서 i의 정체를 알 수 있나??
i의 주소값을 알 수 있으니 알 수 있다.
==> 주소값 연산자(&) 를 통해 해당 식의 주소값을 알아 낼 수 있다.

이동이 가능한가?
아니다 int&& x = i; 는 컴파일 안된다


  • lvalue는 아래와 같은 것들이 있다.
    • 변수, 어떤 타입의 데이터 멤버 (예컨대 std::endl, std::cin) 등등
    • 좌측값 레퍼런스를 리턴하는 함수의 호출식. std::cout << 1 이나 ++it 같은 것들
    • a = b, a += b, a *= b 같이 복합 대입 연산자 식들
    • ++a, --a 같은 전위 증감 연산자 식들
    • a.m, p->m 과 같이 멤버를 참조할 때. 이 때 m 은 enum 값이거나 static 이 아닌 멤버 함수인 경우 제외.
    • a[n] 과 같은 배열 참조 식들
    • 문자열 리터럴 "hi"
       class A {
      int f();        // static 이 아닌 멤버 함수
      static int g(); // static 인 멤버 함수
      }
      A a;
      a.g; //  lvalue
      a.f; //  prvalue

void f(int&& a) {
a; // <-- ?
}
  • a 는 우측값 레퍼런스기는 하지만 함수 내부의 식 a 의 경우는 lvalue 이다.
    왜냐면 주소값을 구할 수 있기 때문이다.
  • 식 a 의 타입 은 우측값 레퍼런스가 맞지만 식 a 의 값 카테고리 는 lvalue가 된다.

prvalue

  • 주소값을 가질 수 없고 그저 표현만 한다(임시객체 = 사라진다)
int f() { return 10; }
f(); 

f()는 주소값을 가져올 수 없다 하지만 우측값 레퍼런스에 넣을 수 있다. ==> prvalue


  • prvalue는 아래와 같은 것들이 있다.
    • 문자열 리터럴을 제외 한 모든 리터럴들. 42, true, nullptr 같은 애들
    • 레퍼런스가 아닌 것을 리턴하는 함수의 호출식. 예를 들어서 str.substr(1, 2), str1+ str2
    • 후위 증감 연산자 식. a++, a--
    • 산술 연산자, 논리 연산자 식들. a + b, a && b, a < b 같은 것들을 말합니다.
      ==> 물론 이들은 연산자 오버로딩 된 경우들 말고 디폴트로 제공되는 것들을 말한다.
    • 주소값 연산자 식 &a
    • a.m, p->m 과 같이 멤버를 참조할 때. 이 때 m 은 enum 값이거나 static 이 아닌 멤버 함수여야함.
    • this
    • enum 값
    • 람다식 { return 0;}; 과 등등 ...

prvalue 들은 식의 좌측에 올 수 없다, 항상 우측에 와야함
상수 좌측값 레퍼런스와 우측값 레퍼런스를 초기화하는데 사용 가능.

const int& r = 42;
int&& rr = 42;

xvalue

  • 이동도 가능하고 주소값으로 정체도 알 수 있는 친구

    우측값 레퍼런스를 리턴하는 함수의 호출식이 있다.

    대표적으로 std::move(x)가 있다


공부한 내용 복습

개인 공부 기록용 블로그입니다.
틀린 부분 있으다면 지적해주시면 감사하겠습니다!!

0개의 댓글