이동 의미구조(Move Semantics) 주의할 점

CppCon 2019: Klaus Iglberger “Back to Basics: Move Semantics (part 2 of 2)” 내용 중 이동 의미구조(Move Semantics) 주의할 점 정리.

 

예제 1

A(T&& t)에서 t는 전달 참조(forwarding reference)이므로 std::move가 아니라 다음처럼 std::forward를 사용해야 한다.

 

예제 2

A(T&& t)는 클래스 템플릿의 생성자이고 T는 클래스 템플릿 매개변수이다. 인스턴스를 생성할 때 타입을 지정하므로 T는 타입 추론에 사용하지 않는다. 즉 t는 오른값 참조이므로 다음처럼 std::move()를 사용해야 한다.

 

예제 3

A(T&& t)에서 t는 전달 참조(forwarding reference)이므로 std::forward를 사용하는 것은 맞다. 하지만 std::forward 역시 조건부 이동을 하므로 같은 오른값을 두 번 이동할 수는 없다. 첫 번째는 다음처럼 복사한다.

 

예제 4

코드 자체는 문제가 없다. 다만 호출하는 쪽에서 t1, t2에 같은 오른값을 대입하면 문제가 될 뿐.

 

예제 5

returnstd::move를 사용해 이동하면 효율적일 것 같지만 RVO(Return Value Optimization, 반환값 최적화)를 하지 않으므로 오히려 좋지 않다. 다음처럼 바로 반환한다. 특히 C++17부터는 복사 생략(copy elision)을 표준으로 보장한다.

한 가지 더 주의할 점은 std::unique_ptr<Widget>&&로 오른값 참조를 반환하지 않는다. 왼값 참조와 마찬가지로 이미 소멸한 객체를 참조하려 할 뿐이다.

 

예제 6

foo()int 형 왼값을 대입하면 Tint&가 돼 의도한 대로 작동하지 않는다. 다음처럼 명시적으로 참조를 제거해야 한다.

 

마지막으로 매개변수와 반환값을 전달할 때 권장 내용은 다음을 참고한다.

 

Notes:
1. 단 NRVO(Named RVO)는 표준에서 보장하지 않는다.
단 NRVO(Named RVO)는 표준에서 보장하지 않는다.

You may also like...