CafeM0ca

[C++] rvalue reference(우측값) 본문

Programming/C++

[C++] rvalue reference(우측값)

M0ca 2018. 7. 9. 02:11
반응형

C++에는 우측값이라는 개념이 존재한다.

우측값? 좌측값?


int main()
{
    int a = 1;     // a는 좌측값 1은 우측값

    int& ref = a;    // ref는 좌측값 a도 우측값이면서 좌측값

    return 0;

}


위 코드에서 a는 왼쪽에 있어서 좌측값이다. 1은 오른쪽에 있어서 우측값이다.

다음줄에 ref는 왼쪽에 있어서 좌측값이다. a는 오른쪽에서 있어서 우측값이지만 a = 1을 통해 동시에 좌측값이다.

따라서 a는 우측값이면서 좌측값이다.

그럼 1 = a;를 생각해보자. 컴파일에러가 뜬다.

1은 우측값이며 좌측값이 아니다.


위 내용을 토대로 다음과 같은 명제가 성립한다.

모든 좌측값은 동시에 우측값이지만 모든 우측값은 좌측값이 아니다.


그럼 '무엇이 우측값인가?'에 대한 질문에 대한 답변은 '임시 변수로 오는것은 우측값으로 보면 된다'이다.

보통 임시 객체는 const type& 형태이다. 우측값은 이를 포인터 주소만 얕게 복사하여 오버헤드를 줄인다.


lvalue

rvalue

rvalue

위 결과가 나온다.


그럼 다음과 같은 코드는 어떻게 할까..


lvalue를 인자로 받는게 없어서 incr(a)를 호출하려하면 컴파일 에러가 발생한다.

그러나 a는 좌측값이면서 동시에 우측값임은 위에서 설명했다.

C++에서는 좌측값을 인자로 받는 함수가 없으면 우측값으로 받는 함수로 연결하지 않는다.

std::move를 사용하면 Lvalue Reference를 Rvalue Reference로 바꿔준다.

이를 이용해 넘겨주면 된다.


다음과 같은 코드는 문제가 있다.


a + b는 10과 20의 합인 30이 된다. 따라서 다음과 같은 코드와 동일하다.


30은 Rvalue다. 따라서 다음과 같이 바꿔주면 된다.



move symantics

move symantics는 move constructor와 move assign operator를 통해서 지원된다. 이 둘은 반드시 noexcept로 선언되어 컴파일러가 예외를 발생시키지 않도록 한다.

간단한 string클래스를 보자.

두번째 생성자를 보면 Rvalue Reference를 통해서 생성 있는데 data는 src->data 주소를 가리키게된다.

그리고 that.data를 nullptr로 만들어 줆으로써 메모리 누수나 Dangling Pointer를 방지한다.

나머지 자료형에 대해서는 얕은 복사를 해주고 파라미터로 넘어온 객체의 멤버변수들을 0으로 초기화해주자.

move symantics은 위와 같은 방식으로 되어있다. == std::move()


이게 어디서 성능이 좋냐?

위와같은 코드가 있다고 가정하고 T가 엄청나게 큰 클래스나 구조체라고 생각해보자.

temp를 만드는데 많은 비용이 들것이다. 변수가 한 두개면 복사하는데 큰 영향이 없지만 그게 백터고 배열이면?? .. 끔찍하다..


이럴때 move symantics를 사용하면 된다. ( 원본 객체가 삭제되는것을 알 때만 유용 )

반응형

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

[C++] unifrom initializing  (0) 2018.07.13
[C++] constexpr  (0) 2018.07.09
[C++]상속 (virtual, override, static)  (0) 2018.06.30
[C++] pimpl(pointer to implementation)  (0) 2018.06.30
[C++] dangling pointer  (0) 2018.06.30
Comments