범위 기반 for

Jaemyeong Lee·2024년 12월 8일

게임 서버1

목록 보기
88/220

핵심 문법

for (const auto& item : container) {
    // item 사용 (읽기 전용, 복사 없음)
}
  • 범위 기반 for는 "컨테이너의 모든 요소"를 간결하게 순회하는 문법입니다.
  • 인덱스보다 요소 자체에 집중할 때 가장 읽기 쉽습니다.

내부적으로 어떻게 동작하나?

아래와 거의 같은 코드로 변환되어 동작합니다.

auto&& __range = container;
for (auto __it = begin(__range), __end = end(__range);
     __it != __end;
     ++__it) {
    auto&& item = *__it;
    // 본문
}
  • 즉, 본질은 begin(), end(), !=, ++, * 기반 이터레이터 순회입니다.
  • 커스텀 컨테이너도 이 규약을 제공하면 range-for를 사용할 수 있습니다.

auto 선택 기준 (값/참조)

for (auto x : vec) {          // 값 복사
    // 원본 변경 안 됨
}

for (auto& x : vec) {         // 비-const 참조
    x *= 2;                   // 원본 변경
}

for (const auto& x : vec) {   // const 참조
    // 읽기 전용 + 복사 없음 (권장 기본값)
}
  • 읽기 전용 순회: const auto& 권장
  • 원본 수정 필요: auto&
  • 작은 기본형(int 등)에서만 auto 값 복사가 부담이 적음

순회 중 삽입/삭제가 위험한 이유

for (auto& x : v) {
    if (x % 2 == 0) {
        // v.erase(...); // 위험: 내부 이터레이터 무효화 가능
    }
}
  • range-for도 내부적으로 이터레이터를 사용하므로, 중간 insert/erase는 순회 상태를 깨뜨릴 수 있습니다.
  • 삭제가 필요하면 Part 8의 패턴 사용:
    • for (it ... ) { it = erase(it); }
    • erase(remove_if(...), end())

인덱스가 필요할 때

range-for는 인덱스를 직접 주지 않습니다. 인덱스가 필요하면 명시적 for가 더 명확합니다.

for (size_t i = 0; i < v.size(); ++i) {
    cout << i << ": " << v[i] << '\n';
}

커스텀 컨테이너에서 range-for 지원 조건

다음이 있으면 기본적으로 동작합니다.

iterator begin();
iterator end();
// const 컨테이너용
const_iterator begin() const;
const_iterator end() const;
  • begin() == end()인 빈 상태도 정확히 표현되어야 합니다.
  • end()는 마지막 다음 위치(센티널)여야 하며 역참조하면 안 됩니다.

자주 하는 실수 + 체크 질문

자주 하는 실수

실수문제
for (auto x : bigVec) 습관화매 반복 복사 비용
순회 중 erase/push_back 수행이터레이터 무효화 위험
수정 의도인데 const auto& 사용컴파일 에러
인덱스가 필요한데 range-for 고집코드 우회/가독성 저하

체크 질문 (스스로 답해보기)

  • 읽기 전용 루프에서 const auto&가 기본 권장인 이유는?
  • range-for 중 원소 삭제가 왜 위험한지 내부 동작 관점으로 설명할 수 있는가?
  • 인덱스가 필요한 상황에서 왜 일반 for가 더 적절한가?

profile
李家네_공부방

0개의 댓글