rvalue

ⓟrogramming/C++ 2016. 5. 11. 12:15
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.


1.

일반적으로 C에서는 

lvalue를 = 의 좌측을 의미한다. (예) int a = 10; 이라고 하면 a 가 lvalue

그런데, 사실 lvalue는 = 를 기준으로 좌측 우측 모두 올 수 있다.

아래 예제를 보게 되면 v1은 lvalue이다. 그런데 v2 = v1; 에서 보는거와 같이 우측에도 올수 가 있다.

결국 좌측 우측이 기준이 아니라 lvalue는 다음과 같이 정의할 수 있다.

1. 이름이 있다. (int a = 10; => a 라는 이름이 있다.)

2. 지속성이 있다. (메모리 어딘가에 저장되어 있고 block이 다른곳에서 사용 가능하다)

3. 주소를 얻을 수 있다. (&a)


아래 goo 함수 또한 reference를 return 하는데 이것도 lvalue이다.

위 const 또한 lvalue 이지만 변경 불가능한 lvalue 이다.


#include 
using namespace std;

int x = 0;

int foo() { return x; }
int& goo() { return x; }

int main()
{
    int v1 = 0, v2 = 0;

    v1 = 10; // v1 : lvalue, 10 : rvalue
             // lvalue는 좌측 우측 모두 올수 있다.

    v2 = v1;
    10 = v1;

    foo() = 10; // foo 는 값이 리턴됨(0 : 문법적으로는 임시객체임)
                // 값을 리턴하는 함수는 rvalue. error

    goo() = 10; // goo 는 진짜 x가 리턴됨
                // 참조를 리턴하는 함수는 lvalue

    int* p1 = &v1;
    int* p2 = &10; // rvalue는 주소를 얻을 수 없다. error
                   // lvalue는 이름이 있지만 rvalue는 이름이 없다
                   // lavlue는 지속성을 가지지만, rvalue는 지속성이 없다.
                   // *임시객체는 rvalue 이다.

    constexpr int c = 10;
    c = 20; // ?? c는 rvalue ?  lvalue?
            // 이름이 있고 메모리 지속성도 있고, 메모리 주소도 찍을 수 있다.
            // lvalue이기는 하지만 변경이 불가능한 lvalue 이다.

    // constant vs literal 
    constexpr int c1 = 10;
    cout << &c1 << endl; // c1은 constant : lvalue
    cout << &10 << endl; // 10 은 literal : rvalue
}
2.
int main()
{
    int n1 = 10;

    // C++98의 참조
    int& r1 = n1; // ok.. lvalue는 참조 가능 (이것을 lvalue reference라고 부름)
    int& r2 = 10; // error. 

    // C++98 const 참조
    const int& r3 = n1; // ok
    const int& r4 = 10; // Const 참조는 lvalue 뿐만 아니라 rvalue도 가르킬수 있다. ok

    // C++11 rvalue reference - rvalue만 참조 가능
    int&& r5 = n1; // error
    int&& r6 = 10; // ok
}
3. 그동안 reference라고 불렀던 것은 실제로 lvalue-reference임.
int main()
{
    int n1 = 10;
 
    // C++98의 참조
    int& r1 = n1; // ok.. lvalue는 참조 가능 (이것을 lvalue reference라고 부름)
    int& r2 = 10; // error. 
 
    // C++98 const 참조
    const int& r3 = n1; // ok
    const int& r4 = 10; // Const 참조는 lvalue 뿐만 아니라 rvalue도 가르킬수 있다. ok
 
    // C++11 rvalue reference - rvalue만 참조 가능
    int&& r5 = n1; // error
    int&& r6 = 10; // ok
}
4. Reference 충돌
typedef int&  LR;
typedef int&& RR;
 
// Reference Collapse : 양쪽이 모두 && 일때만 && 되고, 나머지는 & 이다. 
int main()
{
    int n = 10;
 
    LR r1 = n; // n ? 10
    RR r2 = 10;
 
    LR& r3 = n; // LR& => int& &   => int& // 양쪽이 1개(&) 이므로 결국은 1개이다.
    RR& r4 = n; // RR& => int&& &  => int& // 2개 1개 이므로 결국 1개
 
    LR&& r5 = n; // & && -> &
    RR&& r6 = 10; // && && -> &&
 
    // int && && a = 10; 직접 타이핑해서는 안된다. typedef를 이용해서 충돌나는 경우에만 가능함
}


왜 이런 복잡한 규칙과 문법을 만들었을까?

이걸 이해 하려면 perfect forwarding을 알아야 한다.

'ⓟrogramming > C++' 카테고리의 다른 글

Visual Studio 에서 Boost 사용법  (0) 2016.07.28
임시객체  (1) 2016.05.11
static_assert  (0) 2016.05.10
부분전문화(partial specialization) template  (0) 2016.05.10
Inserting object to C++11 vector without copy constructor  (0) 2015.08.29
블로그 이미지

뚱땡이 우주인

,