인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

dzzzing님의 프로필 이미지

작성한 질문수

홍정모의 따라하며 배우는 C++

9.1 산술 연산자 오버로딩 하기

3분 50초, 사용자정의 자료형 반환 시 복사에 대하여 궁금합니다.

작성

·

108

1

3분 50초 부근에서 강사님께서 "파라미터로 참조를 받아 결과값을 내는 방식이 많이 사용되었지만, 최근에는 해당 자료형을 바로 반환하는 것이 추세이다" 라고 말씀하셨습니다.

해당 객체를 return할때 임시객체를 생성 후 호출부에 반환하며 복사가 이루어지는 것으로 알고 있습니다. 사용자 정의 자료형은 만들기에 따라 크기가 결정되기 때문에 복사비용이 부담이 크다는걸로 압니다. 그렇다면 return과 동시에 객체를 생성하고 반환할 경우에는 복사가 이루어지지 않는 것인지 궁금합니다.

+)

구글링 및 ChatGPT로 검색해본 결과 컴파일러에 의해 최적화 되어서 복사가 일어나지 않도록 한다는데

 

제가 학습한 반환에 의한 복사가 일어나는 개념이 잘못된것인지 궁금합니다.

답변 2

0

durams님의 프로필 이미지

안녕하세요, 질문&답변 도우미 durams입니다.

질문에 대한 답변

참조형 타입을 사용해서 결과값을 반영하는 방식 대신 결과 타입을 바로 반환하는 경우, 불필요한 복사가 일어나는 것이 아닌가 궁금하신 것으로 이해했습니다. 그리고 return과 동시에 객체를 생성하고 반환하는 경우는 아래 코드와 같은 상황을 말씀하시는 것 같네요.

MyClass getObj() {
    return MyClass();    // 임시 객체 반환
}

이 경우에는 RVO (Return Value Optimization) 이라는 최적화가 적용될 수 있습니다. 이것은 함수가 임시 객체를 반환할 때 복사 생성자 호출 없이, 반환되는 대상에 객체를 직접 생성하는 것을 의미합니다.

즉, 우려하시는 불필요한 복사는 RVO 덕분에 발생하지 않습니다. 최적화가 적용되지 않는 전통적인 관점에서는 복사가 발생할 수도 있지만, 최신 언어 구현/컴파일러에서는 이러한 문제를 다양한 방법으로 해결하고 있습니다.


참고

이 부분은 당장은 참고용으로만 읽어두셔도 충분합니다.

RVO와 유사한 개념으로, NRVO (Named Return Value Optimization) 가 있습니다. NRVO는 RVO와 달리 함수의 영역 내 이름이 있는 지역 객체 반환 시 적용될 수 있습니다.

RVO와 NRVO는 모두 Copy elision의 일종으로, C++에서 불필요한 복사를 방지하는 최적화 방법으로 사용됩니다.

C++17부터는 RVO가 선택이 아닌 필수적으로 적용됩니다. 반면 NRVO는 여전히 선택적으로 적용됩니다.

제가 테스트한 결과,

  • MSVC에서는 RVO를 비활성화할 수 없었습니다. 반면 NRVO는 /Zc:nrvo- 옵션을 지정해 비활성화하는 것이 가능했습니다.

  • g++에서는 -fno-elide-constructors 플래그를 사용해 모든 경우에 대해 copy constructor가 생략되지 않도록 copy elision을 비활성화하는 것이 가능합니다.


강의에서 언제 등장하는 개념인가요?

복사 생성자RVO9.9 복사 생성자, 복사 초기화 반환값 최적화에서 배우시게 됩니다. 강의에서 개념이 등장하기 전에 이러한 상황에 대해 미리 생각하시는걸 보면 강의를 꼼꼼히 보시는 것 같아 저도 기분이 좋네요.

위에서 말씀드렸던 내용들은 아직 강의에서 등장하지 않았다 보니, 실습 없이 글만으로 이해하시기는 어려울 수 있다고 생각합니다. 섹션 10. 연산자 오버로딩을 모두 수강하신 후 다시 보시면 좋은 통찰을 얻어가실 수 있을 것 같습니다.

불필요한 객체의 복사를 줄이는 방법은 이 외에도 r-value reference를 이용한 move semantics 구현이 있습니다. 이에 대해서도 섹션 16. 의미론적 이동과 스마트 포인터에서 배우실 예정입니다.


여담으로, 파라미터의 타입으로 참조형을 사용하여 결과값을 반영하는 방식은 C 언어에서부터 많이 사용하던 방식입니다. 특히 성능이 중요한 시스템 프로그래밍에서 많이 사용하며, 반환값으로 에러 유무를 판단하기도 합니다. 영상에서 나온 것처럼, 최근 C++에서는 사용자가 정의한 타입 또는 std::tuple 등의 타입을 반환하는 직관적인 방식도 많이 사용합니다.

도움이 되셨기를 바라며, 더 궁금한 점이 있다면 질문해주세요.

dzzzing님의 프로필 이미지
dzzzing
질문자

정말 필요한 답변 감사합니다! 참고내용도 재밌어보여서 따로 메모해뒀다가 해당 섹션 공부할때 같이 보겠습니다 ㅎㅎ

0

인프런 AI 인턴님의 프로필 이미지

안녕하세요, 인프런 AI 인턴입니다. dzzzing님.

반환 최적화와 관련하여 질문해주신 부분에 대해 설명드리겠습니다.

사용자 정의 자료형을 반환할 때 불필요한 복사를 방지하기 위해 컴파일러가 자동으로 “Return Value Optimization (RVO)” 또는 “Named Return Value Optimization (NRVO)“라고 불리는 최적화 기법을 적용할 수 있습니다. 이러한 기법들은 함수가 객체를 반환할 때, 임시 객체를 만들지 않고 바로 결과를 저장할 수 있도록 해줍니다.

핵심 개념:

  1. Return Value Optimization (RVO):

    • 함수가 객체를 반환할 때, 객체의 복사를 피하고 직접적으로 호출부에 결과를 저장합니다.
    • 컴파일러가 이러한 최적화를 수행함으로써 불필요한 복사를 방지합니다.
  2. Named Return Value Optimization (NRVO):

    • 함수 내에서 미리 선언된 변수를 반환할 때, 그 변수 자체를 호출측에 전달하여 복사를 방지합니다.
    • 이는 RVO의 특수한 형태로 볼 수 있습니다.

위의 두 기법 모두 C++ 컴파일러에서 널리 사용되어 성능 향상을 도모합니다. 컴파일러가 이러한 최적화를 수행할 수 있는 경우, 복사 생성자가 호출되지 않습니다. 하지만, 이 최적화가 항상 보장되는 것은 아니며, 구현에 따라 다를 수 있습니다.

추가 참고 자료:

  • [6:35] 반환값 최적화에 대해서 질문 있습니다: 반환값 최적화에 관한 질문에서 반환값 최적화를 지원하는 상황을 설명하고 있습니다. 질문 확인하기

추가적으로 최적화를 완벽히 이해하고 싶으시다면 자신이 쓰는 특정 컴파일러 문서를 참고하여 어떤 optimization option이 제공되는지도 살펴보시길 권장드립니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

dzzzing님의 프로필 이미지

작성한 질문수

질문하기