Language/C++

C++ 11 :: R-Value Reference

VallistA2015. 2. 14. 18:06

기존의 C++ 레퍼런스 타입에서는.


1.


1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
 
class MyClass
{
 
};
 
int main(void)
{
    MyClass a;
    MyClass& b = a;             // b가 a를 참조하도록 한다.
}


이러한 형식으로 참조를 하게 되었는데. 

C++ 11에서 R-Value Reference 라는 기능이 추가되므로써 R - Value 참조가 가능하게 되었다.


2.


1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
 
class MyClass
{
 
};
 
int main(void)
{
    MyClass a;
    MyClass&& c = a; // 이렇게
}


원래 대입식의 오른쪽은 R-Value를 위한 자리이다. 따라서 이곳에 L-Value가 위치하면 L-Value는 묵시적 그리고 자동으로 R-Value로 변경된다. 따라서 다음 코드는 다 유효하다.


3.


1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
 
int main(void)
{
    int d = 13;    // d는 L-Value, 13은 R-Value
    int f = 12;     // f는 L-Value , 12는 R-Value
 
    d = f;
    f = d;
    d = d * f;
}


첫번째와 두번째 라인은 모두 L-Value에 또 다른 L-Value를 대입한 것으로, 컴파일러의 처리 과정에서 대입식의 오른쪽에 등장하는 L-Value는 자동으로 R-Value로 변환된다.

한편, 맨 마지막 라인의 오른쪽에 등장하는 a*b는 R-Value 이며 반드시 대입식의 오른쪽에 등장해야 한다.


4.


1
2
3
4
5
6
7
#include <iostream>
 
int main(void)
{
    int v = d*f;
    //d * f = 12;
}


두번째 라인은 에러가 난다. R-Value는 반드시 대입식의 오른쪽에 등장해야 한다.

R-Value가 필요한 자리에 L-Value가 등장하면, 묵시적이고 자동으로 R-Value로 변경된다고 했는데 R-Value는 그런 변경이 발생하지 않으며 R-Value는 무조껀 R-Value 자리인 대입식의 오른쪽에 있어야 한다.


또한 위 코드의 변수에 const를 붙여주지 않았으므로 L-Value는 처음 어떤 값으로 정의된 이후에도 또 다른 R-Value를 통해 그 값을 자유롭게 변경할 수 있어야 한다.

반면 R-Value는 일단 정해진것은 변경이 다시 되지 않으며 R-Value는 굳이 const로 지정해주지 않아도 const 성격을 가진다.

L-Value와 R-Value의 정의는 C++에서도 여전히 유효하지만, 이렇게 이해하는 것이더 유용하다.


특정 메모리 위치를 가리키며, 어떤 값을 할당할 수 있고, &연산자를 통해 해당 메모리의 주소값을 가져올 수 있는 표현식이 L-Value 이며 R-Value는 어떤 값을 할당하는 일이 불가능하고, 컴파일러 입장에서 R-Value의 존재이유는 오로지 L-Value에 값을전달하려고 임시적으로 생성된 것일 뿐이다.


첫번째로 알아야 할 것은 R-Value에는 어떠한 값을 담을 수 없다.

당연히 &연산자를 사용해서 내부의 값을 알아오는 일도 할 수 없다는 것이다.

두번째로 알아두어야 할 점은 C++에서 레퍼런스 타입을 반환하는 함수를 호출하면 결과로 L-Value가 반환되고, 이를 제외한 모든 경우는 R-Value가 반환된다는 것이다.


5.


1
2
3
4
5
6
7
8
#include <iostream>
 
int main(void)
{
     int& foo();  // foo 함수는 어딘가에 정의되어있다고 가정
     foo()  = 12;
     int* p1 = &foo();
}


두번째 라인에서는 foo()함수를 호출하고 있으며, 그 결과로 L-Value가 반환된다.

세번째 라인에서는 foo()함수를 호출한 후 그 결과에 & 연산자를 통해 주소값을 가져온다.


6.


1
2
3
4
5
6
7
8
#include <iostream>
 
int main(void)
{
     int bar();
     int j = 0;
     j = bar(); // OK. Bar 함수는 R-Value
}


반면 위 예제에서 정의한 bar() 함수는 레퍼런스 타입을 반환하는 함수가 아니므로, bar() 함수를 호출하면 무조껀 R-Value가 반환된다.

따라서 세 번째 라인처럼 bar() 함수가 대입식의 오른쪽에 등장하는 것은 괜찮지만, 대입식의 왼쪽에 있거나 & 연산자를 사용해 주소값을 알아낼 수는 없다.


R-Value를 사용해야 Move Semantics 를 구현 가능해지며, R-Value는 C++ 11에 추가된 Perfect Forwarding도 해결할 수 있는 개념이다.


마지막 예제를보고 확실하게 파악하도록 하자.


7.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
 
int main(void)
{
        // c++ 98 에서 사용하던 L-Value 레퍼런스 부분
    int a = 1;
 
    // int& r = 3;
    // L-value 레퍼런스의 오른쪽 값은 반드시 L-Value여야 하므로 에러
    int& ra = a;
 
    std::cout << "Original: L-Value(a): " << a << ", L-Value Reference(ra): " << ra << std::endl;
 
    // C++ 11에 새롭게 도입된 R-Value 레퍼런스 부분
    int b = 10;
 
    // R-Value 레퍼런스는 오른쪽 값으로 R-Value나 L-Value 모두 사용 가능
    int && rb = 20;
 
    std::cout << "Original: L-Value(b): " << b << ", R-Value Reference(rb): " << rb << std::endl;
    rb = b;
    std::cout << "Modified: L-Value(b): " << b << ", R-Value Reference(rb): " << rb << std::endl;
 
        return 0;
};


댓글

VallistA

병특이 끝나서 게임에서 웹으로 스위칭한 프로그래머.
프로그래밍 정보등을 공유합니다.
현재는 이 블로그를 운영하지 않습니다.
vallista.kr 로 와주시면 감사하겠습니다!

자고 싶습니다. ㅠㅠ

Github      :: 링크

궁금한점 문의 주시면 답변드리도록 하겠습니다

VISITED

Today :

Total :

SNS

  • 페이스북아이콘
  • 카카오톡아이콘
  • 트위터아이콘

Lately Post

Lately Comment