ONE QUESTION AT A TIME.

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

TODAY’S QUESTION306 / 1500
언어·런타임난이도 하5분 답변 목표 · 보강본

C++에서 복사를 줄이려고 std::move를 붙였습니다. 어떤 경우에는 여전히 복사되며, 이동 뒤 원본은 어떻게 다뤄야 하나요?

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

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

구두 답변

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

std::move 자체가 데이터를 옮기는 것은 아닙니다. 이동할 수 있는 값처럼 취급하도록 형을 바꿔 오버로드 선택에 영향을 줍니다. 실제로 이동 생성자나 대입이 호출되는지, 그 구현이 자원을 넘기는지는 타입에 달려 있습니다. 이동 연산이 없거나 const 객체라면 복사가 선택될 수도 있습니다.

이동 연산이 실제로 하는 일

다음은 std::move가 원본을 비우는 명령 자체는 아님을 보여 주는 예입니다. 필요한 헤더는 <string>과 <utility>입니다.

const std::string source = "hello";
std::string target = std::move(source); // const라서 일반적인 이동 생성자가 아닌 복사 선택

std::move는 const를 제거하지 않습니다. 자원을 빼앗으려면 원본을 변경할 수 있어야 하는데 source는 const이므로 std::string의 해당 생성에서는 복사가 사용됩니다.

큰 버퍼를 소유한 객체를 큐에 넘기는 경우라면 버퍼 주소와 소유권만 전달해 이득을 볼 수 있습니다. 하지만 작은 고정 배열을 가진 타입은 이동도 원소를 옮겨야 하므로 복사와 비슷할 수 있습니다. 저는 성능 문제의 실제 복사 경로를 찾은 다음 그 지점에서 소유권을 넘겨도 되는지 확인하겠습니다. 이름이 move라고 비용이 없다고 판단하지는 않겠습니다.

이동 뒤 원본과 예외 안전성

이동된 객체는 타입 계약에 따라 유효하지만 내용이 정해지지 않은 상태일 수 있습니다. 사용자 정의 타입의 구체적인 moved-from 상태는 그 타입의 자체 계약입니다. 따라서 원래 값을 계속 읽어야 하는 코드에서 무작정 move하면 논리 버그가 생깁니다. 컨테이너 재할당에서는 이동 중 예외가 날 수 있는지에 따라 복사를 선택하는 경우도 있습니다. 반환값 최적화가 가능한 위치에 불필요한 move를 추가하는 것도 피하겠습니다. 복사·이동 횟수와 할당량을 측정하고, 이후 원본 사용과 실패 경로까지 확인해 적용하겠습니다.

선택 기준과 검증

사용자 정의 타입의 이동 후 상태는 표준이 모든 값을 비우라고 정한 것이 아니라 그 타입의 불변식과 문서가 정합니다. 이동 대입은 대상의 기존 자원을 정리해야 하므로 self-move, 예외, 이중 해제를 함께 시험하겠습니다. 최적화의 성공 기준도 std::move 사용 횟수가 아니라 할당·복사 감소와 원본 재사용 규칙의 명확성으로 두겠습니다.

이름 있는 rvalue reference 변수도 표현식으로 사용하면 lvalue입니다. 예를 들어 T&& 매개변수를 다음 함수에 이름으로 넘기면 자동으로 계속 이동되지 않습니다. 항상 소유권을 넘길 자리에는 std::move를, 호출자가 넘긴 값 범주를 보존해야 하는 전달 참조에는 std::forward를 사용하는 이유입니다. 둘을 무조건 치환하면 lvalue까지 뜻하지 않게 소비할 수 있습니다. 이 구분을 값 범주와 완벽 전달의 관점에서 설명하겠습니다.

컨테이너 이동도 항상 포인터 교환만 하는 것은 아닙니다. 이동 대입에서 할당자가 호환되지 않거나 내부에 고정 저장 공간이 있으면 원소별 이동이 필요할 수 있습니다. 명시적으로 삭제된 이동 오버로드가 선택되면 복사로 조용히 대체되는 것이 아니라 컴파일 오류가 될 수도 있습니다. 반환 경로에서는 NRVO와 C++17의 보장된 복사 생략을 구분하고, 생성자 계측이 실제 최적화 조건을 바꾸지 않는지도 확인하겠습니다.

02

득점 포인트

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

  • std::move의 형 변환과 실제 이동 연산을 구분한다.
  • 이동 후 상태·const·NRVO·noexcept를 소유권 판단과 연결한다.
  • 복사 횟수와 할당량을 측정해 최적화를 검증한다.
03

감점 포인트

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

  • std::move가 즉시 데이터를 옮기는 함수라고 설명한다.
  • const 객체나 이동 연산 부재에서도 항상 이동한다고 말한다.
  • 이동 후 원본을 원래 값으로 계속 사용하거나 모든 반환에 move를 붙인다.
04

더 파고들 거리

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

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

원리부터 공부하고 싶다면

답변을 보충하는 개념·예제·슈도코드를 읽어 보세요.

← 전체 질문 보기