C++11에 범위 기반 for문이란 문법이 새로 생겼습니다.
저는 현재 C#을 주로 사용하기 때문에 처음 범위 기반 for문을 접했을 때 “그냥 foreach이네?”라고 생각했지만 새롭게 문법을 추가한 큰 이유를 알게 되었고 이에 대해 정리하였습니다.
1. 기존 for문의 문제점
우리가 for문을 사용하는 큰 이유는 일정 횟수만큼 특정 행위를 반복하기 위함입니다.
여기서 중요한 것이 일정 횟수입니다.
예를 들어, 배열의 요소들을 출력하는 간단한 기능을 만든다고 가정해 봅시다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<iostream>
int main()
{
int arr[] = { 10,20,30 };
for (size_t i = 0; i < 3; i++)
{
std::cout << arr[i] << std::endl;
}
}
// 출력 결과
10
20
30
만약 여기서 배열의 크기가 변경되었다면 반복문을 도는 횟수를 변경해주어야 합니다.
지금은 코드가 간단하기 때문에 큰 문제가 되지 않아 보이지만
코드가 길어진다면 배열의 크기가 변경될 때마다 사용하는 for문을 모두 찾아 변경하기란 불가능에 가깝습니다.
이런 불편함을 해소하기 위해 나온 문법이 범위 기반 for문입니다.
2. 범위 기반 for문
아까와 동일한 배열을 범위 기반 for문으로 구현해 보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
int main()
{
int arr[] = { 10,20,30 };
for (auto e : arr)
std::cout << e << std::endl;
}
// 출력 결과
10
20
30
출력 결과를 보면 기존 for문과 동일한 결과값을 얻을 수 있음을 알 수 있습니다.
기존 for문과 큰 차이점은 배열의 크기를 신경 쓰지 않는다는 점입니다.
그렇기 때문에 배열의 크기가 변경되어도 for문을 수정하지 않아도 정상적으로 코드가 실행됨을 알 수 있습니다.
2-1. 범위 기반 for문 - 요소를 참조하기
만약 아래와 같이 코드를 구현했다면 출력 결과는 어떻게 될까요??
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<iostream>
int main()
{
int arr[] = { 10,20,30 };
for (auto e : arr)
e = 100;
for(auto e : arr)
std::cout << e << std::endl;
}
// 출력 결과
10
20
30
출력 결과는 10 20 30입니다.
즉 e = 100이 적용되지 않았는데요.
이로써 우리는 auto e는 arr의 요소의 값이 복사된 변수임을 알 수 있습니다.
그러므로, auto& e를 통해 값 복사가 아닌 값 참조로 처리를 해야 적용됨을 알 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>
int main()
{
int arr[] = { 10,20,30 };
for (auto& e : arr)
e = 100;
for(auto e : arr)
std::cout << e << std::endl;
}
// 출력 결과
100
100
100
2-2. 범위 기반 for문 - const auto&
만약 데이터를 순회해서 값을 변경하지 않는다면 어떻게 접근하는 게 가장 효율적일까요??
정답은 const auto&라고 생각합니다.
- 값 복사는 객체가 클수록 비효율적임은 모두가 아는 사실입니다. 그러므로 값 복사는 최대한 하지 않는 것이 좋습니다.
- 값이 변경되지 않는다면, 컴파일러에게 변경되지 않음을 선언할 필요가 있습니다.
그럼 컴파일러가 값 변경이 되는지 추적할 필요도 없고 사용자 또한 값이 변경되지 않음을 보장받을 수 있습니다.
그러므로, 참조만 하는 것이면 const auto&를 꼭 사용하는 습관을 들이면 좋을 것 같습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
int main()
{
int arr[] = { 10,20,30 };
for(const auto& e : arr)
std::cout << e << std::endl;
}
// 출력 결과
10
20
30