본문 바로가기
NC University/Advanced C++

5일차 - range-based for loop

by 날쑤 2015. 8. 11.

Intro

  C++ 11으로 넘어오면서 다른 언어가 가진 foreach 개념이 C++에도 도입되었다.

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

int main(int argc, char* argv[])
{
    int x[3] = { 1,2,3 };
    vector<int> v = { 1,2,3,4,5 };

    // 기존(C++ 98)의 for loop
    for (int i=0; i< 3;++)
    {
        cout << x[i] << endl;
    }
  
    // C++ 11부터 도입된 range-based for loop
    for (auto/*data type*/ n : x)
    {
        cout << n << endl;
    }

    // 배열뿐만 아니라 vector도 가능하다.
    for (auto/*data type*/ n : v)
    {
        cout << n << endl;
    }

    return 0;
}

동작 원리

  위 예제에서 vector에 적용된 range-based for 문은 컴파일러에 의해 아래의 코드로 변환된다.

for (auto p = begin(v); p != end(v); ++p)
{
     auto n = *p;
     cout << n << endl;
}

  즉, range-based for 문이 정상적으로 동작하려면 " : " 오른쪽에 오는 대상을 인자로 받는 begin과 end (일반)함수가 정의되어 있어야 한다. 배열, STL 컨테이너, 그리고 initializer_list에 대해서는 라이브러리에 이미 이 함수들이 정의되어 있기 때문에 바로 적용이 가능하다.

응용

  사용자 정의 타입의 객체를 range-based for 문에서 사용하려면 해당 타입에 대한 begin과 end 함수를 명시적으로 구현해줘야 한다. 간단한 예제를 살펴보자.

struct Point3D
{
    Point3D (int a, int b, int c) : x(a), y(b), z(c) {}
    int x, y, z;	
};

// begin과 end 함수를 Point3D 타입에 대해 명시적으로 구현
int* begin (Point3D& p) { return &(p.x); }
int* end (Point3D& p) { return &(p.z) + 1; }  //< end()는 마지막 인자 다음 주소

  Point3D 객체에 대해서도 begin과 end 함수가 존재하므로, 이제는 아래와 같이 Point3D 객체에 대해서도 range-based for 문을 적용할 수 있다.

#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    Point3D p(1, 2, 3);
    for (auto n : p)
    {
        cout << n << endl;
    }
    return 0;
}