IT박스

C ++의 향상된 FOR 루프

itboxs 2021. 1. 5. 07:51
반응형

C ++의 향상된 FOR 루프


Java에서 C ++로 전환하고 있는데 C ++에 Java에서 사용한 향상된 for 루프가 포함되어 있는지 궁금합니다. 예를 들면 다음과 같습니다.

int[] numbers = {1,2,3,4,5,6,7,8,9,10};
for (int item : numbers) {
  System.out.println("Count is: " + item);
}

C ++에서도 동일한 "바로 가기"가 가능합니까?


C ++ 11에서 컴파일러가 지원한다면 그렇습니다. 범위 기반이라고합니다.

std::vector<int> v;

// fill vector

for (const int& i : v) { std::cout << i << "\n"; }

C 스타일 배열 및 함수가 begin()있고 end()반복기를 반환 하는 모든 유형에서 작동 합니다. 예:

class test {
    int* array;
    size_t size;
public:
    test(size_t n) : array(new int[n]), size(n)
    {
        for (int i = 0; i < n; i++) { array[i] = i; }
    }
    ~test() { delete [] array; }
    int* begin() { return array; }
    int* end() { return array + size; }
};

int main()
{
    test T(10);
    for (auto& i : T) {
        std::cout << i;   // prints 0123456789
    }
}

C ++ 11은 그렇습니다. 범위 기반 fors라고합니다. 유형을 const에 대한 참조 또는 참조로 한정해야합니다.

C ++ 03에 대한 해결 방법은 BOOST_FOR_EACH 또는 std :: for_each 와 함께 boost :: bind 입니다 . Boost.Lambda를 사용하면 더 멋진 일이 가능합니다. 자신이나 동료를 좌절시킬 기분이 든다면 더 이상 사용되지 않는 바인더 .std::bind1ststd::bind2nd

다음은 몇 가지 예제 코드입니다.

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <boost/lambda/lambda.hpp>
#include <functional>    

int main()
{
  int i = 0;
  std::vector<int> v;
  std::generate_n(std::back_inserter(v), 10, [&]() {return i++;});

  // range-based for
  // keep it simple
  for(auto a : v)
    std::cout << a << " ";
  std::cout << std::endl;

  // lambda
  // i don't like loops
  std::for_each(v.begin(), v.end(), [](int x) { 
      std::cout << x << " ";
    });
  std::cout << std::endl;

  // hardcore
  // i know my lib
  std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
  std::cout << std::endl;


  // boost lambda
  // this is what google came up with
  // using for the placeholder, otherwise this looks weird
  using namespace boost::lambda;
  std::for_each(v.begin(), v.end(), std::cout << _1 << " ");
  std::cout << std::endl;

  // fold
  // i want to be a haskell programmer
  std::accumulate(v.begin(), v.end(), std::ref(std::cout), 
                  [](std::ostream& o, int i) -> std::ostream& { return o << i << " "; });

  return 0;
}

C ++ 03에는 그러한 가능성이 없습니다. 그러나 새로운 표준 (C ++ 11)에는 그것을 가지고 있습니다. 예제 참조 ( Wikipedia 에서 가져옴 ) :

int my_array[5] = {1, 2, 3, 4, 5};
for (int &x : my_array) {
    x *= 2;
}

std::vector<int>일반 배열 대신 사용 하는 것도 고려하십시오 . 이것은 C 데이터 유형에 대한 C ++ 비유로 삶을 더 쉽게 만듭니다.


예, 아니오.

1. 로컬 어레이 : 아니요,하지만 쉽게 크기를 찾을 수 있습니다.

로컬 배열 ( int numbers[4] = {1, 2, 3, 4];)이 있으면 할 수 있습니다 size = sizeof(numbers) / sizeof(int).

2. Pointer to array: Not at all, you have to pass the size around separately

If you have a pointer to an array (int* numbers = new int[4];) then you can't figure out the size unless you keep track of it yourself. (or if it's null terminated in the case of a c string, but then you have to iterate through it which is linear running time...)

Note that I don't believe pointer to array is the proper terminology, really you just have a pointer to the first element of the array but space for multiple values has been allocated. Not sure what this is called. Maybe just a pointer?

3. STL containers: Yes, and you can do some for loop magic using iterators, or just use indices by getting the size

If you have a vector (std::vector<int> v(3, 0);) then you can iterate through it the following ways:

C++11:

auto it = v.begin();
for (auto it = v.begin(); it != v.end(); it++)
{
    UseElement(*it);
}

Or apparently (also C++11, thanks jrok):

for (const int& i : v) { UseElement(i); }

C++ (pre-11):

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

Or using indices:

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

Furthermore, you can use function pointers or functors with STL containers using std algorithm's for_each (#include <algorithm>) like so:

void foo(int i)
{
    std::cout << i;
}

{
    std::for_each(myvector.begin(), myvector.end(), foo);
}

Others already mentioned that this loop style was added in C++11. However C++11 is even better:

for (auto const& item: numbers)
{
  std::cout << "Count is: " << item << '\n';
}

That way, if you later change the element type of numbers from int to long, or even to some bigint class you wrote yourself, you don't need to change that for loop at all.


In the old standard, C++03 (which is from 2003), the language has no built-in support for that kind of for-loop. There are some artifices you can use with Boost, but imo it's not worth including a whole new library for this small convenience feature.

In the new standard, C++11 (which was released just last summer), this is possible; the syntax looks like this:

MyType array[] = { ... }
for (MyType& x : array) {
    ...
}

Note that I'm using MyType& x, not MyType x. In Java everything is a reference. In C++ references have to be explicit, and you declare them using &. If you don't use references, the for-loop will copy each element of the array into x (which might be expensive to do).

However, C++11 is not fully supported by most compilers yet. I think Microsoft's Visual C++ supports this feature, but I'm not sure.


I find this simple macro very useful. The vast majority of my for loops involve iterating over an STL container:

#define For(it, container) for( typeof((container).begin()) it = (container).begin(); it != (container).end(); ++it)

An example:

vector<int> vector_of_ints;
... // initialize it somehow
For(integer, vector_of_ints) {
    cout << *integer << endl;
}

There are two things to be aware of with this: First, it's an iterator and hence you must dereference it. And second, the second parameter to the For will be evaluated many times. I have played with other approaches, but I keep returning to the simplicity of this.

ReferenceURL : https://stackoverflow.com/questions/8378583/enhanced-for-loops-in-c

반응형