25
C++’s Move Semantics KPU Lusain. Kim

C++’s move semantics

Embed Size (px)

Citation preview

C++’s Move Semantics

KPULusain. Kim

INDEX

▪ C++에서의 Value Type▪ L-Value

▪ L-Value Reference &

▪ R-Value

▪ R-Value Reference &&

▪ 이동의미론▪ 이동의미론

▪ 사용 방법

▪ 사용 예

▪ 함정

▪ noexcept

▪ 템플릿에서의 사용▪ 템플릿에서의 &&

▪ 보편 참조(Universal Reference)

▪ std::forward

C++ Value Type

MSDN : https://msdn.microsoft.com/ko-kr/library/f90831hc.aspx

▪ 명칭의 유래는 대개 왼쪽에 위치할 수 있는 값이기 때문– 정확한정의는아님 !

▪ 단일 식을 넘어 지속되는 값

▪ 이름이 있는 모든 변수는 L-Value

ex)

int a; // a is L-value

char* str = “hello, world!”; // str is L-value

auto ret = Func(a); // ret is L-value

L-Value

▪ 복사되지 않으며 원본을 전달하는 참조

▪ 용도1. 변수에 다른 이름을 붙이고 싶을 때

2. 원본이 존재하는 것을 명시하며 복사하지 않고 매개 인자로 넘길 때

▪ 포인터와의 차이점1. 포인터는 초기화를생략하거나중간에 다른 포인터로값변경이가능

2. L-value는 생성시초기화하여야만 하고, 다른 L-value를 대입할수없음

▪ 참고– MSDN | https://msdn.microsoft.com/ko-kr/library/w7049scy.aspx

L-Value Reference &

▪ 사용법– 변수 선언 시 & 기호를 추가

– 초기화할 인자에는 별도의 기호가붙지 않음

ex)

int a = 15; // a is L-value

int& b = a; // b is L-value reference

b = 5; // assign 5 to b

cout << a; // a is 5

L-Value Reference &

▪ 명칭의 유래는 오른쪽에만 위치할 수 있는 값이기 때문– 정확한정의는아님 !

▪ 유지되지 않는 값– 숫자, 이름이없는문자열, 함수의반환값등

ex)

int a = 5; // 5 is Number. R-value

char* str = “hello, world!”; // “hello, world!” is String. R-value

auto ret = Func(a); // Func(a) is Return Value. R-value

R-Value

▪ L-Value 참조와의구분을위해나타난참조

▪ 참조를통한매개인자의전달에서원본의유지가필요없을때사용

▪ 사용자가구현했을경우이동연산이가능해짐

▪ 용도1. 의미체계이동의구현을 위하여

2. 소유권의 유일성을 보장하기 위하여 : unique_ptr

▪ 참고– MSDN | https://msdn.microsoft.com/ko-kr/library/dd293668.aspx

R-Value Reference &&

▪ 사용법– 변수 선언 시 && 기호를 추가

– L-Value와동일하게 정의 시점에 초기화되어야함

▪ 주의사항– 이름이 있는 변수이기 때문에 R-Value Reference는 L-Value

▪ 예제– 추후 설명

R-Value Reference &&

Q다음예제에서 L-Value와 R-Value를구분해보시오

int x = 3;

const int y = x;

int z = x + y;

int *p = &x;

cout << string{ "hello" };

++x;

x++;

중간 Quiz

Q다음예제에서 L-Value와 R-Value를구분해보시오

int x = 3;

const int y = x;

int z = x + y;

int *p = &x;

cout << string{ "hello" };

++x;

x++;

중간 Quiz

move semantics

MSDN : https://msdn.microsoft.com/ko-kr/library/dd293665.aspx

▪ C++11부터 R-Value Reference를 사용 가능– 이를 통해 R-Value를사용한 연산 가능

▪ R-Value는 임시 값이므로 원본을 그대로 사용해도 괜찮지 않을까?– 원본을 보존하지 않아도 되기때문에 의미체계이동을한다고표현(MSDN)

▪ 기본 자료형(Primitive Type) 은 이동하지않음

이동의미론

▪ R-Value가 아닌데 R-Value로 넘기고 싶은 경우– std::move()함수를 사용

▪ std::move– 인자를 R-Value로형변환시킨다

– 함수이름에속으면안된다. 이함수는이동을보장하지않는다

template<class _Ty>

constexpr remove_reference_t<_Ty>&&

move(_Ty&& _Arg) noexcept

{ // forward _Arg as movable

return (static_cast<remove_reference_t<_Ty>&&>(_Arg));

}

사용방법

▪ STL Container에서원소의삽입은이동연산을지원

class Unit; // 이동 연산을 지원하는 클래스

Unit A;

std::vector<Unit> v;

v.push_back(std::move(A)); // A를 vector에 이동하여 삽입

사용 예

▪ STL Container에서의이동연산은조건이까다로움

class Unit; // 이동 연산을 지원하는 클래스

Unit A;

std::vector<Unit> v;

v.push_back(std::move(A)); // A를 vector에 이동하여 삽입하지 않을 것이다

함정

▪ 이동연산중오류가발생한다면?

▪ 이동연산은예외발생시 rollback이불가능할위험존재– 원본을 보존하지 않기 때문에

– 이 때 예외가 발생하지 않는다는 것을 명시할 필요가 있음

▪ 함수의 뒤에 noexcept 키워드를 붙임으로써컴파일러에게 예외를 발생시키지 않음을 명시– 예외가 발생할 경우, 프로그램이 그냥 종료된다. 중대한 버그의 여지가 되므로 주의할 것.

▪ STL은 모든 이동 연산에 대해 noexcept를 요구– noexcept가 없으면 복사 연산을 호출하도록 구현 move_if_noexcept

noexcept참고 | http://mug896.blog.me/140167721658

At Template

MSDN : https://msdn.microsoft.com/ko-kr/library/dd293668.aspx

▪ 문제 : 템플릿에서다음참조는 R-Value Reference일까?

auto&& ref = data;

auto&& ref = move(data);

템플릿에서의 &&

▪ 템플릿에서는 &&에 L-Value가올수도, R-Value가올수도있음> 템플릿에서 &는 L-Value Reference

▪ 이를보편참조(Universal Reference)라고함– 같은의미로 forward Reference가쓰임

▪ 보편참조가생긴이유– 템플릿에인자가많아질수록

L-Value Ref와 R-Value Ref가섞여쓰일경우의수가기하급수적으로늘어남

– 이를막고자둘모두혼용가능한보편참조가제안됨

Universal Reference

▪ 보편참조가생긴이유– 가변인자템플릿(Variadic Template)에서는인자의완벽전달이불가능

template<class Ty, class Args...>

void func(Ty&& arg, Args&& ...args)

{

// arg의 참조 형식을 알 수 없음

// Universal Reference를 통해 확인

// 어떻게…?

}

Universal Reference

▪ Universal Reference인자를다시매개인자로전달할때이인자가 R-Value인지, L-Value인지확인하기어려움

▪ 표준에서구현된함수존재 : std::forward– 완벽한전달을위한함수

▪ 인자의참조형식이 L-Value든 R-Value든원래참조형식대로 전달

▪ std::move와다른점– std::move는무조건 R-Value Ref로전달

– std::forward는원래 R-Value Ref였던인자만그렇게넘김

std::forward

▪ std::forward를사용하는예

template<class Ty, class Args...>

void func(Ty&& arg, Args&& ...args)

{

// process : arg를 처리하는 어떤 함수

process(std::forward<Ty>(arg));

// 재귀로 다른 인자도 처리할 수 있도록 처리

func(std::forward<Args>(args)...);

}

std::forward

▪ Rvalue Reference and constexpr –김경진– https://mva.microsoft.com/ko/training-courses/-with-c-korea-c--10300?l=8F8JAKd6_7904984382

▪ MSDN– 참조 | https://msdn.microsoft.com/ko-kr/library/dz43scw4.aspx

▪ Effective Modern C++ - Scott Meyers– http://www.aladin.co.kr/shop/wproduct.aspx?ItemId=66541334

참고 자료

Thank you!

2017. 09. Team Warp