ONE QUESTION AT A TIME.

천천히 생각하고, 분명하게.

TODAY’S QUESTION314 / 1500

지역 객체를 반환할 때 std::move를 붙이면 오히려 복사 생략을 방해할 수 있나요?

잠깐, 답변을 보기 전에
먼저 내 말로 설명해 볼까요?

답변과 점검 포인트 펼치기답변 접기
01

구두 답변

정의를 외우기보다, 원리와 조건을 연결해 설명해 보세요.

네. 일반적인 값 반환에서 return std::move(local);은 NRVO를 보장하는 장치가 아니라, 오히려 NRVO 후보였던 표현식을 xvalue로 바꾸는 선택입니다. return local;은 이름 있는 자동 저장 기간 객체를 그대로 반환하므로 NRVO를 시도할 수 있고, 생략되지 않더라도 반환 규칙의 암시적 이동 또는 복사 후보가 남습니다. std::move(local)은 “이 객체의 rvalue 표현식”이 되어 반환 객체와 같은 저장 위치로 합치는 NRVO 형태에서 벗어나므로 이동 생성자를 요구하는 경로가 분명해집니다.

Buffer make() {
    Buffer local;
    return local;             // NRVO 선택 가능
}
Buffer make_moved() {
    Buffer local;
    return std::move(local);  // NRVO 대상이 아니며 이동 경로
}

이동 생성자가 삭제됐거나 접근 불가능하면 두 번째 함수가 컴파일되지 않을 수 있습니다. 이동 생성자가 있더라도 성능이 자동으로 좋아지는 것은 아닙니다. 이동 자체의 비용, noexcept, 내부 버퍼의 소유권 이전을 부담하고 NRVO로 없앨 수 있었던 생성자 호출을 남길 수 있습니다. 지역 객체 반환에서는 먼저 return local;을 유지하고, 명시적 cast가 꼭 필요한 변환이나 overload 선택이 있을 때만 이유를 기록하겠습니다.

판단은 생성자 로그만으로 하지 않고 표준 모드, 반환 타입, 객체의 자동 저장 기간, 복사·이동 생성자의 접근성까지 확인해야 합니다. 실제 실행 결과를 이 답변의 언어 보장으로 확대하지 않습니다.

02

득점 포인트

이해가 드러나는 지점을 확인해 보세요.

  • return local;은 NRVO 후보이지만 return std::move(local);은 xvalue로 바뀌어 NRVO 후보에서 벗어난다는 표현식 차이를 설명합니다.
  • 명시적 이동이 이동 생성자 호출과 비용을 남길 수 있으며, noexcept와 삭제·접근성까지 컴파일 경계로 연결합니다.
03

감점 포인트

놓치기 쉬운 조건과 오해를 짚어 보세요.

  • std::move를 붙이면 항상 더 빠르고 복사 생략이 보장된다고 말하면 안 됩니다.
  • return local;의 생략 실패 가능성을 무시하고 복사·이동 생성자를 모두 삭제한 타입도 항상 컴파일된다고 하면 안 됩니다.
04

더 파고들 거리

하나 더 질문하며 이해의 범위를 넓혀 보세요.

  • 이동 생성자에 로그를 넣은 타입에서 NRVO 선택과 명시적 xvalue 반환의 관찰 차이를 빌드 옵션별로 비교해 보세요.
  • 반환 타입이 지역 타입과 다르고 변환 생성자가 필요한 경우 std::move가 overload 선택을 어떻게 바꾸는지 확인해 보세요.

득점·감점 포인트는 학습용 자기 점검 기준이며, 특정 회사의 실제 채점표가 아닙니다.

← 전체 질문 보기