inflearn logo
강의

Course

Instructor

Hong Jung-mo's C++ Programming: Learning by Doing

15.5 std::unique_ptr

unique pointer return value 질문

817

JUN

3 asked

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 최적화를 깨뜨려 성능 저하를 초래하는 바로 그 현상인가요?

C++

Answer 2

10

honglab

저도 검색을 해봤는데

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

JUN

상세한 답변 감사드립니다!

변수가 메모리에 저장되는 것을 알려주는 강의가 어떤강의였죠

1

461

1

메모리 주소 10진수로 출력

1

650

1

클래스 템플릿 특수화에서 boolalpha로 표현된 리턴값에 대해 질문이 있습니다.

1

496

1

여러가지 리턴 타입에 관한 강의가 어떤 걸까요?

1

529

1

메모리 주소에 관한 질분

0

676

1

인터페이스 클래스에서 reportError의 매개변수에 대해 궁금한 것이 있습니다.

0

545

1

형변환 오버로딩에서 const 관련 질문이 있습니다.

0

439

1

Digit 뒤에 reference를 사용하는 이유

0

504

1

4.2 전역 변수, 정적 변수, 내부 연결, 외부 연결

0

319

1

dat파일이...

0

534

1

TODO:대입 연산자 오버로딩에 대한 소스코드입니다.

0

640

1

복사 생성자 관련 질문이 있습니다.

0

450

1

수업 중 궁금한점이 있습니다.

1

386

1

라이브러리자체가 이해가 되지 않습니다.

0

557

1

마지막 예제 질문

0

299

1

증감연산자 위치에 따른 수행 순서 질문입니다.

0

371

1

단항 연산자 오버로딩에서 return 부분에 질문이 있습니다.

1

408

1

friend함수 관련 질문이 있습니다.

0

308

1

operator+ 정의부분에서 궁금한 것이 있습니다.

0

443

1

3분 17초 질문

0

346

1

함수에 값을 대입한다는 개념이 이해가 되지 않습니다.

0

443

1

int getvalue() const에서 const는 왜 뒤에 붙는건가요?

0

440

2

const Something &st에서 const를 빼면 안되나요?

0

296

1

friend함수는 다른 클래스의 멤버함수로 쓸 수 없나요??

1

489

1