C++0x 미리보기 10, 범위 기반 for 루프
대중적으로 인기 있는 C++0x 기능인 범위 기반 for 루프를 간단히 설명하고, 한 가지 주의점도 이야기합니다.
- 제안의 명칭: Proposal for new for-loop
- 제안자: Thorsten Ottosen, Doug Gregor
- 관련 문서: N2049, N2196, N2243, N2394
아마도 가장 잘 알려진, 그리고 auto와 함께 가장 환영 받는 C++0x 기능이 바로 범위 기반 for 루프일 것입니다. 설명하기도 간단합니다. int 벡터의 모든 요소를 출력한다고 합시다. 기존 C++에서는 이런 코드가 필요합니다.
vector<int> vec = ...;
for(vector<int>::iterator itr = vec.begin();
itr != vec.end(); ++itr)
std::cout << *itr;
C++0x의 auto 새 용법(나중에 다른 글에서 다루겠습니다)을 사용하면 조금 더 간결하게 만들 수 있겠지만, C++0x에서 좀 더 직접적인 방식은 다음처럼 범위 기반 for를 이용하는 것입니다.
for( int i : vec )
std::cout << i;
STL 컨테이너 뿐만 아니라 기본 배열도 가능하고, 또한 배열의 원소들을 수정하는 것도 가능합니다. 다음은 그 둘을 모두 보여주는 예입니다.
int array[5] = { 1, 2, 3, 4, 5 }; // 보통의 배열
for (int& x : array) // int가 아니라 int&
x *= 2; // 해당 요소가 실제로 변경됨
최종 사용자가 범위 기반 for에 대해 알아야 할 것은 이게 다입니다. 굳이 한 가지 더 추가하자면, 루프 변수가 반드시 for 문 자체에서 선언된 지역 변수이어야 한다는 점입니다. 즉, 다음은 유효하지 않습니다.
int array[] = ...
int i = -1;
for(i : array) // 오류
...
코딩 스타일에 따라서는 이것이 심각한 제약일 수도 있겠습니다. 예를 들어 순차 검색을 다음과 같이 구현하는 분들도 있을 것입니다.
vector<int>::iterator itr = vec.begin();
for(; itr != vec.end(); ++itr)
{
if (*itr == to_find) break;
}
if (itr != vec.end()) // 찾았음
...
범위 기반 for는 이런 방식을 지원하지 않습니다. 따라서 이를테면 bool found 같은 변수를 따로 두어야 합니다. 개인적으로는 하나의 변수를 여러 가지 용도(이 경우 찾은 항목과 검색 성공 여부)로 사용하는 것은 바람직하지 않다고 생각하며, 따라서 이러한 제약이 오히려 좋은 코딩 스타일을 권장하는 효과를 낼 것이라고 생각합니다. 여러분들은 어떠신지?
예전 댓글(읽기 전용)
-
Lechuck, 2009-01-03 00:01 :
-
저 역시 그렇게 생각합니다. 실제로 int i 같은 문장은 for 문 안에서만 선언하고, 바깥에서 선언한 것을 갖고 들어오지 않습니다. 초심자 시절에 헷갈려서 한 번 덴 적이 있거든요.
-
klutzy, 2009-01-06 14:01 :
Lechuck// msvc6에 for문에 선언한 로컬 변수가 for문 이후에도 살아있는 버그가 있었을 거에요.
전 Java5부터 이 방식으로 쓰다보니 상당히 익숙해져있었는데, C++에서도 편해지겠군요. 변수가 for 루프 안에 정의되어야하는 제약을 보니 문득 생각나는건데, 아래와 같이 사용하는경우 에러가 안나야 하는게 정상인데, 예전 msvc6에서는 에러가 났던걸로 기억하는데, 이건 C++표준에서 정해져있는건지 컴파일러 제작사에 맡기는건지 궁금하네요. for (int x : vect) { ... } for (int x : vect) { ... }