Programing

'for'루프를 사용하여 C ++ 벡터를 반복

crosscheck 2020. 7. 21. 07:52
반응형

'for'루프를 사용하여 C ++ 벡터를 반복


저는 C ++ 언어를 처음 사용합니다. 나는 벡터를 사용하기 시작했으며, 모든 코드에서 인덱스를 통해 벡터를 반복하는 것으로 보았을 때 for루프 의 첫 번째 매개 변수 는 항상 벡터를 기반으로하는 것입니다. Java에서는 ArrayList를 사용하여 이와 같은 작업을 수행 할 수 있습니다.

for(int i=0; i < vector.size(); i++){
   vector[i].doSomething();
}

C ++에서 이것을 볼 수없는 이유가 있습니까? 나쁜 습관입니까?


C ++에서 이것을 볼 수없는 이유가 있습니까? 나쁜 습관입니까?

아닙니다. 나쁜 습관은 아니지만 다음과 같은 접근 방식으로 코드에 유연성을 부여 있습니다.

일반적으로 C ++ 11 이전의 컨테이너 요소를 반복하는 코드는 다음과 같은 반복자를 사용합니다.

std::vector<int>::iterator it = vector.begin();

코드가 더 유연 해지기 때문입니다.

모든 표준 라이브러리 컨테이너는 반복자를 지원하고 제공합니다. 나중에 개발 시점에서 다른 컨테이너로 전환해야하는 경우이 코드를 변경할 필요가 없습니다.

참고 : 가능한 모든 표준 라이브러리 컨테이너에서 작동하는 코드를 작성하는 것이 쉽지 않은 것 같습니다.


이러한 관행을 보지 못하는 이유는 매우 주관적이며 명확한 대답을 할 수 없습니다 iterator. 스타일 코드가 아닌 언급 된 방식을 사용하는 많은 코드를 보았 기 때문 입니다.

사람들 vector.size()이 반복 방법을 고려하지 않는 이유는 다음 과 같습니다.

  1. size()루프 조건에서 매번 호출하는 것에 대해 편집증이 됩니다. 그러나 문제가 아니거나 사소하게 수정 될 수 있습니다.
  2. 루프 자체 std::for_each()보다 선호for
  3. 나중에에서 컨테이너를 변경 std::vector다른 하나 (예에 map, list때문에하지 모든 컨테이너 지원, 또한 루프 메커니즘의 변화를 요구할 것이다) size()반복의 스타일

C ++ 11은 컨테이너를 통해 이동할 수있는 좋은 기능을 제공합니다. 이를 "range based for loop"(또는 Java에서 "enhanced for loop")라고합니다.

작은 코드로 전체를 통과 할 수 있습니다 (필수!) std::vector:

vector<int> vi;
...
for(int i : vi) 
  cout << "i = " << i << endl;

벡터를 반복하는 가장 깨끗한 방법은 반복자를 사용하는 것입니다.

for (auto it = begin (vector); it != end (vector); ++it) {
    it->doSomething ();
}

또는 (위와 동일)

for (auto & element : vector) {
    element.doSomething ();
}

C ++ 0x 이전에는 auto를 반복자 유형으로 바꾸고 전역 함수 시작 및 종료 대신 멤버 함수를 사용해야합니다.

이것은 아마도 당신이 본 것입니다. 언급 한 접근 방식과 비교할 때 장점은의 유형에 크게 의존하지 않는다는 것입니다 vector. vector다른 "컬렉션 유형"클래스로 변경 하면 코드가 여전히 작동합니다. 그러나 Java에서도 비슷한 작업을 수행 할 수 있습니다. 개념적으로 큰 차이는 없습니다. 그러나 C ++은 템플릿을 사용하여이를 구현합니다 (Java의 제네릭과 비교). 따라서 접근하는 모든 종류의 작동 beginend도 같은 정적 배열과 같은 비 클래스 유형에 대해 정의되는 함수. 여기를 참조하십시오 : 일반 배열에 대한 범위 기반은 어떻게 작동합니까?


올바른 방법은 다음과 같습니다.

for(std::vector<T>::iterator it = v.begin(); it != v.end(); ++it) {
    it->doSomething();
 }

여기서 T는 벡터 내부의 클래스 유형입니다. 예를 들어 클래스가 CActivity 인 경우 T 대신 CActivity를 작성하십시오.

이 유형의 방법은 모든 STL에서 작동합니다 (벡터뿐만 아니라 조금 더 좋습니다).

여전히 인덱스를 사용하려는 경우 방법은 다음과 같습니다.

for(std::vector<T>::size_type i = 0; i != v.size(); i++) {
    v[i].doSomething();
}

반복자를 사용해야하는 몇 가지 강력한 이유가 있습니다. 그 중 일부는 여기에 언급되어 있습니다.

나중에 컨테이너를 전환해도 코드가 무효화되지 않습니다.

즉, std :: vector에서 std :: list 또는 std :: set으로 이동하면 포함 된 값을 얻기 위해 숫자 인덱스를 사용할 수 없습니다. 반복자를 사용하는 것은 여전히 ​​유효합니다.

유효하지 않은 반복의 런타임 캐치

루프 중간에 컨테이너를 수정하면 다음에 반복기를 사용할 때 잘못된 반복자 예외가 발생합니다.


STL을 사용하면 프로그래머는 iterators컨테이너를 통과하는 데 사용 합니다. 반복자는 모든 표준 컨테이너에 구현 된 추상 개념이기 때문입니다. 예를 들어 std::list전혀 없습니다 operator [].


I was surprised nobody mentioned that iterating through an array with an integer index makes it easy for you to write faulty code by subscripting an array with the wrong index. For example, if you have nested loops using i and j as indices, you might incorrectly subscript an array with j rather than i and thus introduce a fault into the program.

In contrast, the other forms listed here, namely the range based for loop, and iterators, are a lot less error prone. The language's semantics and the compiler's type checking mechanism will prevent you from accidentally accessing an array using the wrong index.

참고URL : https://stackoverflow.com/questions/12702561/iterate-through-a-c-vector-using-a-for-loop

반응형