범위 기반 for 문 (range-based for statement)
'06.06 - for 문' 포스트에서 for 문을 사용하여 배열의 각 요소를 반복하는 예제를 봤다.
#include <iostream>
int main()
{
const int numStudents = 5;
int scores[numStudents] = { 84, 92, 76, 81, 56 };
int maxScore = 0; // keep track of our largest score
for (int student = 0; student < numStudents; ++student)
if (scores[student] > maxScore)
maxScore = scores[student];
std::cout << "The best score was " << maxScore << '\n';
return 0;
}
for 문은 배열을 반복할 때 편리하고 유연한 방법을 제공하지만, 조금 복잡하고 실수로 인해 오류가 발생하기 쉽다.
C++ 11에서는 범위 기반 for 문(ranged-based for statement)이라는 새로운 유형의 루프를 도입하여 더 간단하고 안전하게 배열 등의 모든 요소를 반복하는 방법을 제공한다.
Ranged-based for loops
범위 기반 for 문(ranged-based for statement)의 문법은 다음과 같다.
for (element_declaration : array)
statement;
루프는 각 array
의 요소를 반복하여 element_declaration
에 선언된 변수에 현재 배열 요소의 값을 할당한다. 최상의 결과를 얻으려면 element_declaration
이 배열 요소와 같은 자료형이어야 한다. 그렇지 않으면 형 변환이 발생한다.
범위 기반 for 문을 사용해서 fibonacci 배열의 모든 요소를 출력하는 예제:
#include <iostream>
int main()
{
int fibonacci[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 };
for (int number : fibonacci) // iterate over array fibonacci
std::cout << number << ' '; // we access the array element for this iteration through variable number
return 0;
}
// 0 1 1 2 3 5 8 13 21 34 55 89
먼저 for 루프가 실행되고 변수 number에 fibonacci 배열의 첫 번째 요소값인 0이 할당된다. 그다음 프로그램에서 0을 출력하는 명령문을 실행한다. 그런 다음 for 루프가 다시 실행되고 number가 두 번째 요소값인 2로 할당된다. 명령문이 다시 실행되어 1을 출력한다. for 루프는 반복할 배열에 원소가 남아있지 않을 때까지 이와 같은 작업을 차례로 반복한다.
배열에 대한 인덱스가 아니라 배열의 요소값이 number에 할당된다.
Ranged-based for loops and the auto keyword
element_declaration
은 배열 요소와 같은 자료형을 가져야 하므로, auto 키워드를 사용해서 C++이 자료형을 추론하도록 하는 것이 이상적이다.
#include <iostream>
int main()
{
int fibonacci[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 };
for (auto number : fibonacci) // type is auto, so number has its type deduced from the fibonacci array
std::cout << number << ' ';
return 0;
}
Ranged-based for loops and references
위에서 본 예제들에서 element_declaration
은 값으로 선언된다.
int array[5] = { 9, 7, 5, 3, 1 };
for (auto element: array) // element will be a copy of the current array element
std::cout << element << ' ';
반복된 각 배열 요소가 element
에 복사된다. 배열 요소를 복사하는 것은 비용이 많이들 수 있다. 다행히도 다음과 같이 참조를 사용할 수 있다.
int array[5] = { 9, 7, 5, 3, 1 };
for (auto &element: array) // The ampersand makes element a reference to the actual array element, preventing a copy from being made
std::cout << element << ' ';
위 예제에서 element
는 현재 반복된 배열 요소에 대한 참조이므로 값이 복사되지 않는다. 또한, element
를 수정하면 배열의 요소에 영향을 미친다.
읽기 전용으로 사용하려는 경우 element
를 const로 만드는 것이 좋다.
int array[5] = { 9, 7, 5, 3, 1 };
for (const auto& element: array) // element is a const reference to the currently iterated array element
std::cout << element << ' ';
성능상의 이유로 ranged-based for 루프에서 참조 또는 const 참조를 사용하는 게 좋다.
Rewriting the max scores example using a ranged-based for loop
다음은 범위 기반 for 루프(ranged-based for loop)를 사용해서 다시 작성한 처음 예제다.
#include <iostream>
int main()
{
const int numStudents = 5;
int scores[numStudents] = { 84, 92, 76, 81, 56 };
int maxScore = 0; // keep track of our largest score
for (const auto& score: scores) // iterate over array scores, assigning each value in turn to variable score
if (score > maxScore)
maxScore = score;
std::cout << "The best score was " << maxScore << '\n';
return 0;
}
위 예에서, 더는 수동으로 배열을 첨자화할 필요가 없다. 변수 score
을 통해 배열 요소에 직접 접근할 수 있다.
Ranged-based for loops and non-arrays
범위 기반 for 루프(ranged-based for loop)는 고정 배열뿐만 아니라 std::vector
, std::list
, std::set
, std::map
과 같은 구조에서도 작동한다. 방금 언급한 것들을 아직 배우지 않았으므로 무엇인지 몰라도 걱정하지 않아도 된다. ranged-based for 문이 유연하다는 것만 기억하면 된다.
#include <vector>
#include <iostream>
int main()
{
std::vector<int> fibonacci = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 }; // note use of std::vector here rather than a fixed array
for (const auto& number : fibonacci)
std::cout << number << ' ';
return 0;
}
Ranged-based for loops doesn’t work with pointers to an array
포인터로 변환된 배열에서 범위 기반 for 루프를 사용할 수 없다. (배열의 크기를 알지 못하기 때문이다.)
#include <iostream>
int sumArray(int array[]) // array is a pointer
{
int sum = 0;
for (const auto& number : array) // compile error, the size of array isn't known
sum += number;
return sum;
}
int main()
{
int array[5] = { 9, 7, 5, 3, 1 };
std::cout << sumArray(array); // array decays into a pointer here
return 0;
}
마찬가지로, 동적 배열은 같은 이유로 범위 기반 for 루프와 작동하지 않는다.
번역: 이 포스트의 원문은 http://www.learncpp.com/cpp-tutorial/6-12a-for-each-loops/ 입니다.