Fundamental of CS/: : C++

[Vector / Array] Vector Loop

Jay.P Morgan 2024. 7. 31. 20:14

 

 

벡터(배열)의 for문 순회 방법

이번 시간에는 벡터(Vector)나 배열(Array)을 순회하는 방법과 각 방식의 특징, 그리고 실수하기 쉬운 부분에 대해 알아보겠습니다.

1. 벡터를 순회하는 세 가지 방법

벡터를 순회하는 방법은 크게 세 가지입니다.

  1. 인덱스 기반(for문)
  2. 이터레이터(iterator) 기반
  3. Range-based for문(C++11 이후)

이터레이터와 Range-based for문은 내부적으로 유사하게 동작하며, 일반적으로 Range-based for문이 가장 안전하고 가독성이 좋은 방법입니다. 다만, 인덱스 값이 필요한 경우에는 인덱스 기반 반복문을 사용하는 것이 적합합니다.


2. 성능 차이는 거의 없다

인덱스, 이터레이터, Range-based for문의 성능을 비교하면 컴파일 옵션이나 실행 환경에 따라 결과가 달라질 수 있습니다.

  • 어떤 경우에는 인덱스 기반이 조금 더 빠르고,
  • 어떤 경우에는 Range-based for문이 더 빠를 수도 있습니다.

즉, 실제 성능 차이는 매우 작으며 일반적인 코드에서는 크게 신경 쓸 필요가 없습니다.

따라서 특별한 이유가 없다면 가독성과 안전성이 높은 Range-based for문을 사용하는 것이 권장됩니다.


3. 인덱스 기반 반복문이 필요한 경우

반복문 안에서 벡터의 크기를 변경하는 작업(삽입, 삭제 등) 이 이루어진다면 상황이 달라집니다.

예를 들어 반복문 안에서 push_back()이나 emplace_back()을 호출하면 벡터의 메모리가 재할당될 수 있습니다.

이 경우

  • 이터레이터는 기존 메모리를 가리키고 있기 때문에 무효화(Invalidation) 될 수 있습니다.
  • 이후 이터레이터를 계속 사용하면 잘못된 메모리를 참조하여 예상하지 못한 동작이 발생할 수 있습니다.

반면 인덱스 기반 반복문은 현재 벡터의 크기와 인덱스를 기준으로 접근하기 때문에, 벡터가 재할당되더라도 정상적으로 동작합니다.


4. Iterator Invalidation

벡터는 연속된 메모리를 사용하는 컨테이너입니다.

공간이 부족한 상태에서 새로운 원소를 추가하면

  1. 더 큰 메모리를 새로 할당하고,
  2. 기존 데이터를 모두 새로운 공간으로 이동한 뒤,
  3. 기존 메모리를 해제합니다.

이 과정이 발생하면 기존 이터레이터는 더 이상 유효하지 않게 됩니다.

따라서 반복문 안에서 벡터의 크기를 변경하는 경우에는 이터레이터 기반 또는 Range-based for문을 사용하면 문제가 발생할 수 있습니다.


정리

  • 벡터를 순회하는 방법은 인덱스 기반, 이터레이터 기반, Range-based for문의 세 가지가 있습니다.
  • 일반적인 상황에서는 Range-based for문이 가장 안전하고 가독성이 좋아 권장됩니다.
  • 인덱스가 필요한 경우에는 인덱스 기반 반복문을 사용하면 됩니다.
  • 반복문 내부에서 벡터의 크기가 변경되는 경우에는 반드시 인덱스 기반 반복문을 사용하는 것이 안전합니다.
  • 벡터의 재할당이 발생하면 이터레이터가 무효화(iterator invalidation) 될 수 있으므로 주의해야 합니다.

다음 시간에는 벡터에서 자주 사용되는 Erase-Remove Idiom에 대해 알아보겠습니다. 이 기법은 실무와 프로그래밍 인터뷰에서도 자주 등장하는 중요한 내용입니다.