프로그래밍 언어/C/C++

[C++11] Range based for loop

소혼 2013. 11. 13. 06:31
반응형

목차로 가기


<개인적으로 공부한 내용들로, 내용이 완벽하지 않을 수 있습니다. 부족한 부분/틀린 부분에 대한 Comment 환영합니다.>


- 업데이트

 * 박진수님이 지적해주신 오타 수정


C++11 에는 새로운 형태의 for loop인 range based for loop를 지원합니다.

이미 python같은 언어에서는 지원되던 기능이기도 합니다.


python에서는 아래처럼 루프를 사용할 수 있었습니다.

### python

peoples = ['ryuan', 'yesum',  'w.third']
for p in peoples:
   print 'people :', p


이것을 c++에서 구현하려면 아래와 같이 해야 할 것입니다.


### c++

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

int main()
{
    vector<string> s;
    s.push_back("ryuan");
    s.push_back("yesum");
    s.push_back("w.third");

    for (vector<string>::iterator i = s.begin(); i != s.end(); ++i)
        cout << "people :" << *i << endl;

    return 0;
}


물론 auto의 등장으로 for loop는 아래처럼 간단해질 수 있습니다.

### c++

    for (auto i = s.begin(); i != s.end(); ++i)
        cout << "people :" << *i << endl;


하지만, 만약 vector대신 2차원 배열로 바꾸려고 하면 어떻게 해야 할까요?

### c++

int main()
{
    const char *s[3] = { "ryuan", "yesum", "w.third" };

    for (int i = 0; i != 3; ++i)
        cout << "people :" << s[i] << endl;

    return 0;
}


이제 range based for loop를 쓰면 아래와 같습니다.

### c++

int main()
{
    //const char *s[3] = { "ryuan", "yesum", "w.third" };
    vector<string> s;
    s.push_back("ryuan");
    s.push_back("yesum");
    s.push_back("w.third");

    for (auto i : s)
        cout << "people :" << i << endl;

    return 0;
}


vector를 쓰던, 배열을 쓰던 동일합니다.


주의할 점은 range loop의 인자 i 는 반드시 loop안에서 선언되어야 한다는 점입니다. 만약 loop밖에서 선언하고 안에서 사용하지 않는다면 아래처럼 에러가 날 것입니다.(gcc)

range_for_loop.cpp: In function ‘int main()’:
range_for_loop.cpp:10:12: error: found ‘:’ in nested-name-specifier, expected ‘::’
range_for_loop.cpp:10:10: error: ‘i’ is not a class, namespace, or enumeration
range_for_loop.cpp:10:15: error: expected ‘;’ before ‘)’ token
range_for_loop.cpp:13:5: error: expected primary-expression before ‘return’
range_for_loop.cpp:13:5: error: expected ‘;’ before ‘return’
range_for_loop.cpp:13:5: error: expected primary-expression before ‘return’
range_for_loop.cpp:13:5: error: expected ‘)’ before ‘return’


그럼 만약, 내가 만든 클래스를 range based for loop로 사용하고자 한다면 어떻게 하면 될까요?

물론 이런 경우가 흔하진 않겠지만, 간단한 class를 만들어보도록 하겠습니다.

### c++

#include <iostream>

class IntList
{
public:
    class Iterator {
    public:
        Iterator(const IntList* p, int pos)
            : m_p(p)
            , m_pos(pos)
        { }

        // Range based for loop use below methods
        bool operator!=(const Iterator& other) const { return m_pos != other.m_pos; }
        int operator*() const { return m_p->get(m_pos); }

        const Iterator operator++()
        {
            //little bit tricky
            ++m_pos;
            return *this;
        }
    private:
        const IntList* m_p;
        int m_pos;
    };

    IntList()
    {
        for (int i = 0; i < 10; ++i)
            m_arr[i] = i;
    }
   
    int get(int i) const { return m_arr[i]; }
    Iterator begin() const { return Iterator(this, 0); }
    Iterator end() const { return Iterator(this, 10); }
private:
    int m_arr[10];
};

int main()
{
    IntList list;
    for (auto i : list)
        std::cout << i << std::endl;
    return 0;

}

실제로 쓸모는 없지만, range based for loop 는 동작합니다.

결국,

begin(), end()를 제공하고, 이때 반환되는 iterator 클래스에서 operator++, operator*, operator!=을 구현하면 됩니다.








참조 : http://www.cplusplus.com/forum/beginner/99989/

참조 : http://www.cprogramming.com/c++11/c++11-ranged-for-loop.html

반응형

'프로그래밍 언어 > C/C++' 카테고리의 다른 글

[C++11] std::function의 성능  (0) 2015.05.29
GCC options  (0) 2013.12.05
[C++11] Move semantics  (5) 2013.11.10
[c++11] rvalue reference  (1) 2013.11.07
[C++11] Variadic template  (0) 2013.11.06