문제

C ++에서 벡터를 반복하는 올바른 방법은 무엇입니까?

이 두 코드 조각을 고려하십시오. 이것은 잘 작동합니다.

for (unsigned i=0; i < polygon.size(); i++) {
    sum += polygon[i];
}

그리고 이것:

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

생성됩니다 warning: comparison between signed and unsigned integer expressions.

나는 C ++의 세계에서 새롭고 unsigned 가변은 나에게 조금 무섭게 보이고 unsigned 올바르게 사용하지 않으면 변수가 위험 할 수 있습니다. 이것이 맞습니까?

도움이 되었습니까?

해결책

뒤로 반복

보다 이 답변.

반복 전진

이것은 거의 동일합니다. 반복자 / 스왑 감소를 증분으로 변경하십시오. 반복자를 선호해야합니다. 어떤 사람들은 당신에게 사용하라고 말합니다 std::size_t 인덱스 변수 유형으로 그러나 휴대용은 아닙니다. 항상 사용하십시오 size_type 컨테이너의 typedef (전방 반복 케이스에서 변환만으로 도망 갈 수는 있지만 사용시 뒤로 반복 케이스에서 실제로 잘못 될 수 있습니다. std::size_t, 경우를 대비하여 std::size_t Typedef보다 넓습니다 size_type):

STD :: 벡터 사용

반복자 사용

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

중요한 것은 항상 정의가 모르는 반복자에게 접두사 증분 양식을 사용하는 것입니다. 이는 코드가 가능한 한 일반적인 실행되도록합니다.

범위 C ++ 11

for(auto const& value: a) {
     /* std::cout << value; ... */

인덱스 사용

for(std::vector<int>::size_type i = 0; i != v.size(); i++) {
    /* std::cout << v[i]; ... */
}

배열 사용

반복자 사용

for(element_type* it = a; it != (a + (sizeof a / sizeof *a)); it++) {
    /* std::cout << *it; ... */
}

범위 C ++ 11

for(auto const& value: a) {
     /* std::cout << value; ... */

인덱스 사용

for(std::size_t i = 0; i != (sizeof a / sizeof *a); i++) {
    /* std::cout << a[i]; ... */
}

후진 반복 답변에서 어떤 문제가 있는지 읽으십시오 sizeof 그러나 접근 방식은 결과적으로 산출 할 수 있습니다.

다른 팁

4 년이 지났고 Google 이 답변을 주었다. 이랑 기준 C ++ 11 (일명 C ++ 0x) 실제로이 작업을 수행하는 새로운 유쾌한 방법이 있습니다 (뒤로 호환되는 가격으로) : 새로운 auto 예어. 사용하기 위해 사용하는 반복자 유형 (벡터 유형을 다시 반복)을 명시 적으로 지정 해야하는 고통을 절약 할 수 있습니다. 와 함께 v 당신의 vector, 당신은 다음과 같은 일을 할 수 있습니다.

for ( auto i = v.begin(); i != v.end(); i++ ) {
    std::cout << *i << std::endl;
}

C ++ 11 더 나아가 벡터와 같은 컬렉션을 반복하기위한 특별한 구문을 제공합니다. 그것은 항상 같은 것을 쓰는 것을 제거합니다.

for ( auto &i : v ) {
    std::cout << i << std::endl;
}

작업 프로그램에서 그것을 보려면 파일을 작성하십시오. auto.cpp:

#include <vector>
#include <iostream>

int main(void) {
    std::vector<int> v = std::vector<int>();
    v.push_back(17);
    v.push_back(12);
    v.push_back(23);
    v.push_back(42);
    for ( auto &i : v ) {
        std::cout << i << std::endl;
    }
    return 0;
}

이것을 쓰는 시점에서, 당신이 이것을 컴파일 할 때 G ++, 당신은 일반적으로 추가 깃발을 제공하여 새로운 표준으로 작동하도록 설정해야합니다.

g++ -std=c++0x -o auto auto.cpp

이제 예제를 실행할 수 있습니다.

$ ./auto
17
12
23
42

참고하십시오 컴파일 및 실행에 대한 지침은 GNU C ++ 컴파일러 켜기 리눅스, 프로그램은 플랫폼 (및 컴파일러)이어야합니다.

예제의 특정 경우에 STL 알고리즘을 사용하여이를 달성했습니다.

#include <numeric> 

sum = std::accumulate( polygon.begin(), polygon.end(), 0 );

더 일반이지만 여전히 간단한 경우에는 다음과 같이 갈 것입니다.

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

using namespace boost::lambda;
std::for_each( polygon.begin(), polygon.end(), sum += _1 );

Johannes Schaub의 답변에 관해 :

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

일부 컴파일러와 함께 작동하지만 GCC는 아닙니다. 여기서 문제는 std :: vector :: iterator가 유형, 변수 (멤버) 또는 함수 (메소드)인지 문제입니다. GCC로 다음과 같은 오류가 발생합니다.

In member function ‘void MyClass<T>::myMethod()’:
error: expected `;' before ‘it’
error: ‘it’ was not declared in this scope
In member function ‘void MyClass<T>::sort() [with T = MyClass]’:
instantiated from ‘void MyClass<T>::run() [with T = MyClass]’
instantiated from here
dependent-name ‘std::vector<T*,std::allocator<T*> >::iterator’ is parsed as a non-type, but instantiation yields a type
note: say ‘typename std::vector<T*,std::allocator<T*> >::iterator’ if a type is meant

솔루션은 다음과 같이 키워드 '타이프 이름'을 사용합니다.

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

전화 vector<T>::size() 유형 값을 반환합니다 std::vector<T>::size_type, int가 아니거나 서명되지 않은 int 또는 기타.

또한 일반적으로 C ++의 컨테이너 위의 반복은 사용합니다. 반복자, 이와 같이.

std::vector<T>::iterator i = polygon.begin();
std::vector<T>::iterator end = polygon.end();

for(; i != end; i++){
    sum += *i;
}

여기서 t는 벡터에 저장하는 데이터 유형입니다.

또는 다른 반복 알고리즘 사용 (std::transform, std::copy, std::fill, std::for_each 등등).

사용 size_t :

for (size_t i=0; i < polygon.size(); i++)

인용 위키 백과:

stdlib.h 및 stddef.h 헤더 파일은 size_t 객체의 크기를 나타내는 데 사용됩니다. 크기를 취하는 라이브러리 기능은 유형 일 것으로 기대합니다. size_t, 운영자의 크기는 평가합니다 size_t.

실제 유형 size_t 플랫폼 의존적입니다. 일반적인 실수는 가정하는 것입니다 size_t 서명되지 않은 INT와 동일하며, 특히 64 비트 아키텍처가 더 널리 퍼져서 프로그래밍 오류로 이어질 수 있습니다.

나는 보통 boost_foreach를 사용합니다.

#include <boost/foreach.hpp>

BOOST_FOREACH( vector_type::value_type& value, v ) {
    // do something with 'value'
}

STL 컨테이너, 어레이, C 스타일 스트링 등에서 작동합니다.

약간의 역사 :

숫자가 음수인지 컴퓨터인지 여부를 나타내려면 '부호'비트를 사용합니다. int 서명 된 데이터 유형은 양수 및 음수 값 (약 -20 억에서 2 억)을 보유 할 수 있음을 의미합니다. Unsigned 양수 만 저장할 수 있으며 (메타 데이터에 약간 낭비되지 않기 때문에 더 많은 것을 저장할 수 있습니다 : 0 ~ 약 40 억).

std::vector::size() 반환합니다 unsigned, 벡터의 길이는 어떻게 음의 길이를 가질 수 있습니까?

경고는 불평등 명세서의 올바른 피연산자가 왼쪽보다 더 많은 데이터를 보유 할 수 있음을 알려줍니다.

기본적으로 20 억 명이 넘는 항목이있는 벡터가 있고 정수를 사용하여 오버 플로우 문제를 겪게됩니다 (INT는 20 억으로 마이너스로 돌아갑니다).

완료하려면 C ++ 11 구문은 반복자 용 서로 버전 만 가능합니다 (심판):

for(auto it=std::begin(polygon); it!=std::end(polygon); ++it) {
  // do something with *it
}

역 반복에도 편안합니다

for(auto it=std::end(polygon)-1; it!=std::begin(polygon)-1; --it) {
  // do something with *it
}

C ++ 11

나는 일반 알고리즘과 같은 일반 알고리즘을 사용합니다 for_each 올바른 유형의 반복자 및 람다 표현식을 검색하지 않으려면 추가 명명 된 기능/객체를 피하십시오.

특정 사례에 대한 짧은 "예쁜"예제 (다각형이 정수의 벡터라고 가정) :

for_each(polygon.begin(), polygon.end(), [&sum](int i){ sum += i; });

테스트 : http://ideone.com/i6ethd

잊지 마세요 포함: 알고리즘 및 물론 벡터 :)

Microsoft는 실제로 이것에 대한 좋은 예를 가지고 있습니다.
원천: http://msdn.microsoft.com/en-us/library/dd293608.aspx

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int main() 
{
   // Create a vector object that contains 10 elements.
   vector<int> v;
   for (int i = 1; i < 10; ++i) {
      v.push_back(i);
   }

   // Count the number of even numbers in the vector by 
   // using the for_each function and a lambda.
   int evenCount = 0;
   for_each(v.begin(), v.end(), [&evenCount] (int n) {
      cout << n;
      if (n % 2 == 0) {
         cout << " is even " << endl;
         ++evenCount;
      } else {
         cout << " is odd " << endl;
      }
   });

   // Print the count of even numbers to the console.
   cout << "There are " << evenCount 
        << " even numbers in the vector." << endl;
}
for (vector<int>::iterator it = polygon.begin(); it != polygon.end(); it++)
    sum += *it; 

첫 번째는 올바른 유형이며 엄격한 의미에서 정확합니다. (당신이 생각한다면, 크기는 결코 0보다 적을 수 없습니다.) 그 경고는 나를 무시하기위한 좋은 후보 중 하나로 나를 때렸다.

Consider whether you need to iterate at all

The <algorithm> standard header provides us with facilities for this:

using std::begin;  // allows argument-dependent lookup even
using std::end;    // if the container type is unknown here
auto sum = std::accumulate(begin(polygon), end(polygon), 0);

Other functions in the algorithm library perform common tasks - make sure you know what's available if you want to save yourself effort.

Obscure but important detail: if you say "for(auto it)" as follows, you get a copy of the object, not the actual element:

struct Xs{int i} x;
x.i = 0;
vector <Xs> v;
v.push_back(x);
for(auto it : v)
    it.i = 1;         // doesn't change the element v[0]

To modify the elements of the vector, you need to define the iterator as a reference:

for(auto &it : v)

If your compiler supports it, you could use a range based for to access the vector elements:

vector<float> vertices{ 1.0, 2.0, 3.0 };

for(float vertex: vertices){
    std::cout << vertex << " ";
}

Prints: 1 2 3 . Note, you can't use this technique for changing the elements of the vector.

The two code segments work the same. However, unsigned int" route is correct. Using unsigned int types will work better with the vector in the instance you used it. Calling the size() member function on a vector returns an unsigned integer value, so you want to be comparing the variable "i" to a value of its own type.

Also, if you are still a little uneasy about how "unsigned int" looks in your code, try "uint". This is basically a shortened version of "unsigned int" and it works exactly the same. You also don't need to include other headers to use it.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top