작성
·
653
6
안녕하세요 교수님. 강의 14분 26초에
auto doSomething2(std::unique_ptr<Resource> res)
{
// ...
return res;
}
여기에서 저는 res가 l-value이기 때문에 return을 할 때
std::unique_ptr<Resource> temp(res)
와 같은 형태(반환값인 임시 개체를 복사 생성하는 형태)가 되어서 copy constructor가 호출 될거라 예상을 했는데요. 교수님이 구현하신 AutoPtr로 실험을 해보니 실제로는 move constructor가 호출이 됐습니다. (move constructor를 지운 상태에서는 copy constructor가 호출이 됩니다. Debug 모드일 때 이렇고 Release 모드에서는 이 때 아무것도 호출이 되지 않았습니다.)
이렇게 되는 이유가 res는 비록 l-value이지만 return문 이후로 사라지는 개체이니 컴파일러가 임시 개체처럼 취급하는 건가요?
또 한 가지 궁금한 것이, 이렇게 return 할 때 정확히 무슨 constructor가 호출이 되고 하는 것들이 아무래도 RVO가 개입하고, 또 Debug 모드일 때와 Release 모드일 때 다르게 동작하니까 정확한 원칙을 파악하기가 좀 어려운데요. RVO가 정확히 어떻게 동작하고 Debug 모드일 때 Release 모드일 때 각각 어떻게 동작하는지까지 정확히 알아야하나요?
추가
위처럼 함수에서 포인터가 아닌 개체를 직접 반환할 때
return std::move(res);
처럼 r-value를 반환하는 것은 오히려 컴파일러의 RVO 최적화를 깨뜨려 성능 저하를 초래할 수 있다고 알고 있는데요. 역시 AutoPtr로 직접 실험을 해보니 Debug 모드에서는 두 경우 모두 move constructor가 호출이 되었으나 Release 모드에서는 l-value로 반환을 하면 move assignment operator만 호출되는데 std::move를 이용해 r-value로 반환을 했더니 오히려 move constructor와 move assignment operator가 모두 호출이 되었습니다. 이것이 RVO 최적화를 깨뜨려 성능 저하를 초래하는 바로 그 현상인가요?
답변 2
9
저도 검색을 해봤는데
move constructor called on return instead of copy
https://stackoverflow.com/questions/45336433/move-constructor-called-on-return-instead-of-copy
이런 글을 찾을 수 있었습니다.
답변 중에 '긴 얘기를 짧게 정리'한 부분을 보면
Long story short, return implicitly tries to move what you return when it makes sense.
즉, move 를 할 수 있는 상황이면 해준다고 하네요.
It will only copy as a last resort (no move constructor available, for example).
이 문장은 복사는 최후의 수단이라는 의미인데 위에 실험하신 내용과 부합하는 것 같습니다. (move constructor를 없애버리면 copy 호출)
추가에서 copy assignment operator인지 move assignment operator인지에 따라 다를 텐데 번거롭게 되는 것 자체가 좋아보이지 않네요.
최적화에 대해서는 저도 계속 공부하는 입장입니다만, 알고리즘 관점에서 최적화를 시도하는 것이 좋고, 이렇게 매우 low level에서 최적화를 고민하는 것은 비효율적이라는 것이 일반적인 견해입니다. 예를 들어서 리턴할 때 move 두 번 실행된다고 해서 전체 프로그램의 효율을 크게 떨어뜨리지는 않는다는 것이지요. 그보다는 데이터를 모두 돌면서 계산하는 작업을 줄인다든가 GPU를 쓴다든가 병렬처리를 한다든가, 아니면 알고리즘 수준에서 반복 회수 자체를 줄여버린다든가 하는 쪽에 집중하라는 것입니다.
그리고 한 가지 더, unique_ptr을 굳이 move로 return하는 것이 unique_ptr의 설계 의도와 맞는지도 잘 모르겠습니다.
0