2012-04-03 2 views
36

C++11에는 모든 요소에 대해 두 개의 루프가 있습니다 (for 및 for_each 기반 범위). 하나가 다른 것을 선호하거나 어떤 것이 더 적합한 상황이 있습니까?기본 표준 사용 : 표준 기반 범위 : for_each

for (auto& elem: container) { 
    // do something with elem 
} 

std::for_each(container.begin(), container.end(), 
       [](Elem& elem) { 
       // do something with elem 
       }); 

내 생각을 가장 먼저 간단하고 두 번째는 또한 완전한 용기없는 시퀀스 작동하고 두 번째는 다른 std -algorithms 더 유사 동안 다른 언어를 기반으로 루프를 범위로 유사하다고 할 것이다.

+0

는 사실 제대로에 대한 범위 기반 * 사용 * 그래서 내 질문 http://stackoverflow.com/questions/9994789/proper-style-for-declaration-in를 참조하십시오하는 방법에 대해 궁금합니다 -range-based- – Potatoswatter

+0

간단한 for_each 예제를 추가했습니다. 나는 하나를 요구하는 메시지를 보았다고 생각했지만 더 이상 확신 할 수는 없다. – juanchopanza

+0

@juanchopanza : 나는 람다를 기반으로 한 질문을했지만, 나는 그 의견을 게시 할 당시 나는 그것을 제거했다. lambda를 질의하는 것이 불가능하다는 Potatoswatter의 의견을 읽으십시오. 그럼에도 불구하고 for_each가 더 적합 할 수있는 좋은 예입니다. – stefaanv

답변

26
  1. 범위 기반 for은 분명히 읽기 쉽고 쓰기가 쉽습니다. 이 작업에 특화되어 있습니다.

    편집 : 예외를 남용하지 않고 범위를 벗어날 수 있습니다. (std::for_each 치환 std::find_if뿐만 아니라이를 수 있지만).

  2. std::for_each, 아이러니하게도, 실제로 기초 범위와 대신 전체 용기의 특정 beginend 값을 선택할 수있는 대안이다. (EDIT은 : ​​이 같은 부스트 ​​의해 제공 beginend 부재를 제공하는 간단한 range 클래스를 사용하여 주위를 해킹 할 수있다.) 달리 고차 함수를 이용할 경우도

    for_each 더 고급 수있다 : 그것은 이용할 수있다 bind의 인수로, 세 번째 인수는 이미 functor입니다.

주로 스타일의 문제입니다. 대부분의 독자는 아마도 for (auto &a : b)을 선호하지만 대부분의 구현에서이 기능을 지원합니다.

+0

+1 사실, for_each에서 범위를 선택할 수 있다는 사실은 매우 강력합니다. – juanchopanza

+5

@juanchopanza : 물론'Range' 컨테이너 (예 :'Boost.Range')를 사용하면이 장점은 유용하지 않습니다. –

+5

휴식 시간을 허용하고 계속하기 위해 범위 만 추가 할 수 있습니다. – Klaim

10

std::for_each은 루프에서 내부적으로 사용 된 펑터를 반환하므로 시퀀스의 요소와 관련된 일부 정보를 수집 할 수있는 깨끗한 메커니즘을 제공합니다. 루프를 기반으로하는 범위는 단지 루프 일 뿐이므로 루프 외부에서 사용될 모든 상태는 해당 범위 외부에서 선언되어야합니다. 귀하의 예에서, 루프의 목적이 서열의 각 요소를 돌연변이시키는 것이라면, 그다지 큰 차이는 없습니다. 그러나 for_each의 반환 값을 사용하지 않는다면 간단한 루프를 사용하는 것이 더 나을 것입니다. 그런데 범위 기반 루프는 C 스타일 배열과 std :: strings에서도 작동합니다.

이것은 상상력이나 유용하지는 않지만 for_each의 반환 값을 사용하는 예입니다. 아이디어를 설명하기 만하면됩니다.

#include <iostream> 
#include <array> 
#include <algorithm> 

struct Foo { 
    void operator()(int i) { if (i > 4) sum += i;} 
    int sum{0}; 
}; 

int main() { 

    std::array<int, 10> a{1,2,3,4,5,6,7,8,9,10}; 
    Foo foo = std::for_each(a.begin(), a.end(), Foo()); 
    std::cout << "Sum " << foo.sum << "\n"; 
} 
+1

+1하지만, 어쨌든 람다 펑터를 질의 할 방법이 없다는 것에주의하십시오; 보조 상태를 얻는 것은 캡쳐 변수를 통해 이루어지며, 이는 어느 구성에서나 동일하게 작동합니다. – Potatoswatter

+0

@Potatoswatter 좋은 지적. 또는 람다로부터 함수 객체를 생성합니다. – juanchopanza

+2

@ juanchopanza : 실제로 상황이 다행스럽게도 C++ 03에서 개선되었습니다. C++ 3에서는 전체 결과 (사본 때문에)를 얻을 수 있으면 지정되지 않았고 C++ 11에서는 이동 작업 만 사용되었습니다. –