티스토리 뷰

반응형

C++에서 반복문의 대명사 for문으로 배열이나 container에 순차적으로 접근할 수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream> // cout
#include <vector> // vector
#include <algorithm> // for_each
using namespace std;
 
int main() {
    vector<int> nums = {12345};
 
    // 1. using for loop
    for (int i = 0; i < 5; i++){
        cout << nums[i] << ' '// vector의 원소를 순차적으로 출력
    }
 
    // 2. using ranged-based for loop
    for (auto &i: nums) {
        cout << i << ' '// vector의 원소를 순차적으로 출력
        i += 2// 각 원소에 2를 더해줌.
    }
}
cs

 

다만, 각 원소에 대한 작업을 쉽게 해 줄 수 있는 STL 함수가 있으니, std::for_each로 한 번에 처리하여보자.

for_each에 대하여 알아보자.


1. for_each

(※ https://www.cplusplus.com/reference/algorithm/for_each/에서 함수에 대한 정보를 확인할 수 있다.)

 

C++의 알고리즘 관련 헤더 <algorithm.h>에는 for_each라는 함수는 다음과 같은 구조를 가진다.

 

Function for_each(InputIterator first, InputIterator last, Function fn)

 

for_each는 3개의 인자를 받는다.

  • InputIterator first: 배열이나 어떤 container 자료형의 시작부 혹은 포인터
  • InputIterator last: 배열이나 어떤 container 자료형의 끝부 혹은 포인터
  • Function fn: 배열이나 container의 각 원소에 수행할, 인자가 1개인 함수. 함수 객체와 함수 포인터 모두 가능하다. 이 함수의 반환값은 무시된다.

 

for_each 함수의 반환값은 전달된 함수 객체이므로, 보통 무시해도 된다.

 

구체적으로 이 함수의 역할을 말하자면, 범위 [first, last)에서 각 원소에 적용할 함수 fn을 적용한다. for_each 함수는 기존 원소를 변형하기에 기존 원소를 보존하거나 결과를 다른 곳에 보관할 경우 다른 함수를 사용해야 한다. 만약 이해가 안 된다면, 같은 역할을 하는 코드를 작성하면 다음과 같이 작성할 수 있다.

 

1
2
3
4
5
6
7
8
9
10
template <class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function fn) {
 
    while (first!=last) {
        fn (*first);
        ++first;
      }
 
  return fn;  // C++11 이후부터는 move(fn)
}
cs

 

쉽게 말해, 배열 안의 값들에 함수를 적용시켜준다고 할 수 있다.


2. 예제 코드

위의 각 배열을 for문 대신 for_each를 이용하여 출력하고, 각 원소에 2를 더한다고 하면, 다음과 같이 작성할 수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream> // cout
#include <vector> // vector
#include <algorithm> // for_each
using namespace std;
 
void func(const int& x) {
    cout << x << ' ';
}
int add_2(int& x) {
    x += 2;
    return 100// return값은 무시됨.
}
 
int main() {
    vector<int> nums = {12345};
 
    // for_each를 이용한 출력
    for_each(nums.begin(), nums.end(), func);
    
    // 각 원소에 2를 더함
    for_each(nums.begin(), nums.end(), add_2);
    for (const auto& x: nums) {
        cout << x << ' ';
    }
 
    // cout : 3 4 5 6 7
}
cs

 

이렇게 쓰고 나면, for문과 같은 역할을 하지 않냐는 이야기를 할 수 있다.

 

옳은 이야기이다. for_each는 for문과 거의 동일한 역할을 하고 있다고 해도 무방하다.  적용할 함수의 인자로 레퍼런스를 사용한다면 원소 내의 값도 수정할 수 있다. C++11부터 지원되는 range-based for문이 도입됨에 따라 for_each 함수의 필요성은 거의 사라졌다.

 

그래도 사용하는 이유를 꼽자면, for_each를 사용하면 함수로 코드를 관리하기 때문에 코드의 가독성을 높일 수 있다.

 

또한, C++17부터는 STL 병렬화를 위한 Execution Policy를 직접 인자로 추가할 수 있고, 이는 for문과는 다른 양상을 띄게 된다. 이 이야기는 ExecutionPolicy에 관한 이야기를 할 때 하겠다.

 

도움이 되었다면 지나가는 길에 하트 하나 눌러주세요, 양질의 글을 쓰는데 하나의 동기부여가 됩니다😍

지적이나 오타 수정 댓글 환영합니다!!

 

 

반응형
댓글
Total
Today
Yesterday
공지사항
최근에 올라온 글
최근에 달린 댓글
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함