2010-02-15 3 views
7

std :: list를 통해 이중 루프를 수행하여 각 요소 쌍을 처리하려고합니다. 그러나 두 번째 반복기를 초기화하는 데 문제가 있습니다. 내가 쓰고 싶습니다 코드는 다음과 같습니다증가하는 루프에서 std :: list iterator를 생성하는 방법

리스트 반복자는 랜덤 액세스하지 않기 때문에 작동하지 않습니다, 그래서 당신이 일을 할 수없는
for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) { 
    for(std::list<int>::iterator j = i+1; j != l.end(); ++j) { 
     ... 
    } 
} 

. 그러나 나는 깔끔한 대안을 찾는 데 어려움을 겪고있다. 컴파일러는 내가 희망을 가지고있는 std::list<int>::iterator j(i)++;을 가지고 매우 행복해 보이지 않습니다. 내가 원하는 것을 얻으려면 for 루프의 구조에 잘 맞지 않는 약간의 어색함이 필요하다.

명백한 대안이 있습니다 (예를 들어 벡터를 사용합니다!)하지만 지금은 볼 수없는 합리적으로 깔끔한 방법이 있어야합니다. 사전에 어떤 도움

감사합니다 :) 위로 경기에서

답변

7

간결하게하기 :

// for consistency, 
template <typename Iter> 
void increment(Iter& pIter) 
{ 
    ++pIter; 
} 

template <typename Iter> 
Iter increment_copy(Iter pIter) 
{ 
    return ++pIter; 
} 

// ... 

typedef std::list<int> int_list; 

for(int_list::iterator i = l.begin(); i != l.end(); ++i) 
{ 
    for(int_list::iterator j = increment_copy(i); j != l.end(); ++j) 
    { 
    } 
} 
4
for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) { 
    std::list<int>::iterator j = i; ++j; 
    for(; j != l.end(); ++j) { 
     ... 
    } 
} 

!

실제로이 수치는 수치 알고리즘에서 꽤 일반적인 관용구이므로보기 흉한 것으로 보지 않습니다. 난 그냥 생각을거야

for (std::list<int>::iterator i = l.begin(); i != l.end(); ++i) { 
    for (std::list<int>::iterator j = i; ++j != l.end();) { 
     // ... 
    } 
} 
9
for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) { 
    std::list<int>::iterator j = i; 
    for(std::advance(j, 1); j != l.end(); ++j) { 
     ... 
    } 
} 
+0

'advance'는 반환 값이 없으므로 첫 번째 인수를 수정합니다. (나는 개인적으로 싫어한다.) 그렇다고'advance_copy' 함수를 작성하는 것은 쉽다. – GManNickG

+0

@GMan : 수정 됨. 타이! – dirkgently

+0

문제 없습니다. 나는 대체 대답으로 내 생각을 함께 가기로 결심했다. – GManNickG

2

나는에 dirkgently의 대답했다 : 당신은 너무 유틸리티 기능의 또 다른 클래스를 만들 수 있습니다

template <typename Iter, typename Dist> 
Iter advance_copy(Iter pIter, const Dist& pOffset) 
{ 
    std::advance(pIter, pOffset); 

    return pIter; 
} 

// ... 

typedef std::list<int> int_list; 

for(int_list::iterator i = l.begin(); i != l.end(); ++i) 
{ 
    for(int_list::iterator j = advance_copy(i, 1); j != l.end(); ++j) 
    { 
    } 
} 

을, 도움에 대해 어떻게

1

나는

for (std::list<int>::iterator i = l.begin(); i != l.end(); ++i) { 
    std::list<int>::iterator j(i); 
    while(++j != l.end()) { 
     // ... 
    } 
} 
0

이미 부스트를 사용하는 경우, 가장 쉬운 방법은 boost::next을 사용하는 것입니다 : R 션의 제안은,를 제외하고는 while 루프합니다.

for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) 
    for(std::list<int>::iterator j = boost::next(i); j != l.end(); ++j) 
+0

부스트가 내 생각을 훔쳤다는 뜻입니다. :( – GManNickG

2

똑 바른 "깔끔한"대안 은 (내장 타입의 반대),리스트 반복자가 과부하 사업자와 사용자 정의 형식의 개체라는 사실을 기반으로 할 수 있습니다. 물론 이것은 공식적으로 보장되지는 않지만 목록 컨테이너의 특성을 기반으로 이것을 기대할 수 있습니다. 이러한 이유 때문에 오버로드 된 접두어 ++ 연산자를 목록 반복자 유형의 임시 객체에 적용 할 수 있습니다.

방금, i의 임시 복사본을 만드는 접두사 ++를 사용하여 증가하고 j

for(std::list<int>::iterator i = l.begin(); i != l.end(); ++i) { 
    for(std::list<int>::iterator j = ++std::list<int>::iterator(i); j != l.end(); ++j) { 
    ... 
    } 
} 

를 초기화하는 결과 값을 사용할 필요가 무엇을 원하는 달성하기 위해 그리고 바로 그거야. 이 트릭은 꽤 인기가 있으며 때로는 실제 코드에서 발생할 수 있습니다. 또한 많은 구현체가 일반적인 내장 포인터를 벡터 반복자로 사용하기 때문에 일반적으로 std::vector에서는 작동하지 않지만, 일반적으로 std::list과 함께 작동합니다.

그러나 개인적으로 저는 실제로이 코드를 사용하지 않을 것입니다.여분의 코드 줄을 추가하여 좋은 결과를 얻었습니다.

관련 문제