프로그래밍C++ 개발자

C++에서 'lvalue'와 'rvalue'는 무엇인가요? 그들의 차이점, 함수에 전달하는 방법, 그리고 rvalue 참조가 왜 생겼는지 설명해주세요.

Hintsage AI 어시스턴트로 면접 통과

답변

C++에서 lvalue (왼쪽 값)는 메모리의 객체를 참조하는 표현식으로 이름이 있으며 참조할 수 있는 것입니다(예: 변수). rvalue (오른쪽 값)는 이름이 없는 임시 값으로 전통적인 의미의 객체가 아닙니다(예: a + b의 결과, 타입 5의 리터럴).

lvalue는 주소를 가져올 수 있지만, rvalue는 그렇지 않습니다 (rvalue 참조가 등장하기 전까지). 이들을 함수에 전달하기 위해서는 다음과 같은 방법이 있습니다:

  • 일반 참조: void foo(const std::string& s); — lvalue와 rvalue를 모두 받습니다.
  • Lvalue 참조: void bar(std::string& s); — lvalue만 받습니다.
  • Rvalue 참조 (C++11+): void baz(std::string&& s); — rvalue만 받습니다.

예제:

void takeValue(std::string& s) { } // lvalue void takeRValue(std::string&& s) { } // rvalue std::string s = "hello"; takeValue(s); // OK, lvalue takeRValue(std::string("hi")); // OK, rvalue

rvalue 참조는 주로 자원을 복사하는 것이 아니라 이동하기 위해 임시 객체를 효율적으로 전달하는 데 필요합니다.

트릭 질문

표현식 std::move(obj)가 어떤 유형의 참조(lvalue 또는 rvalue)를 받을 것인가요? std::move를 적용한 후 객체는 어떤 카테고리에 속하게 되나요?

답변:

std::move(obj)는 항상 rvalue 참조 (T&&)를 반환하지만, 객체 자체는 여전히 lvalue로 남아 있으며 단지 명시적 변환이 적용됩니다. 이후에는 객체를 극도로 조심스럽게 처리해야 합니다 (정의되지 않았지만 유효한 상태일 수 있습니다).

예제:

std::string s = "data"; std::string d = std::move(s); // d는 s의 데이터를 얻고, s는 이제 비어있음

주제에 대한 미숙지로 인한 실제 오류 예


이야기

대형 프로젝트에서 한 개발자는 임시 객체를 lvalue 참조 T&를 통해 전달했습니다 (대신 T&& 또는 const T&). 이는 컴파일 오류와 비효율적인 복사를 초래했습니다 — move 의미론이 사용되지 않아 성능이 40% 감소했습니다.


이야기

프론트엔드 엔진에서 std::move가 잘못 적용되어 다시 사용한 변수들이 있었습니다. 이로 인해 변수들이 "파괴된" 상태가 되었고, 이로 인해 예외가 발생하고 렌더 스레드가 충돌했습니다.


이야기

직렬화 라이브러리에서 std::vector<T> 타입의 컨테이너를 함수에 lvalue로 전달했지만 이동(movable)을 기대하였습니다. 이동 대신 많은 요소의 비싼 복사가 진행되어 큰 배열의 직렬화 시간이 급격히 악화되었습니다.