2009-08-07 4 views
21

간단한 질문. for 루프 각 루프에 재 평가에 조건이루프 상태 평가

for (int i = 0; i < dim * dim; i++) 

인가 :

나는 다음과 같습니다 루프가?

그렇다면이

int dimSquare = dim * dim; 
for (int i = 0; i < dimSquare; i++) 

감사

-Faken

답변

32

일반적으로 루프 내에서 "희미한"값을 변경하면 매번 다시 평가됩니다. 그러나 당신의 예제에서는 그렇지 않기 때문에 괜찮은 컴파일러는 코드를 최적화 할 것이고 성능에 어떤 차이도 보이지 않을 것입니다.

+0

매우 오랜 생각을 가진 사람에게 미안하지만,이 대답은 모든 것을 분명하고 간결한 방식으로 설명해주었습니다. – Faken

+3

그러나 루프 제어에 로컬 변수를 사용하는 것에 대한 bdonlan의 제안을 잊지 말아야합니다. 로컬 사용자는 가시성이 제한되어 있으므로 컴파일러가 최적화하기가 더 쉽습니다 (컴파일러 최적화뿐만 아니라 독자의 이해에 도움이 될 수 있음). –

+0

내가 너라면 사과하지 않을거야. 이것은 bdonlan에게 "포퓰리스트"뱃지에서 괜찮은 기회를 제공합니다. 글을 올렸을 때 9 표를 얻었고 Lulu가 다른 8 점을 얻었을 때 –

-4

컴파일러는 루프 전에 희미한 * 희미한의 값을 미리 계산됩니다? :처럼, 무언가를하는 것이 더 효율적이 될 것입니다 시작

+0

Dim을 루프 내부에서 수정할 수있는 경우가 아니면. –

+0

그래서 for 루프에서 희미한 값이 변경되는 경우에도 미리 컴파일 된 값에 도달 할 때까지 루프가 실행됩니다. 또는 루프를 통해 어둑한 변화가있을 때 프로그램에서 다시 평가할 것인가? – Faken

+1

@Faken, Dim 변경의 가능성이 있다면 컴파일러는 _every_ loop를 다시 평가합니다. – bdonlan

44

예, 의미 상 모든 루프마다 평가됩니다. 의 경우, 컴파일러 은 항상 자동으로 루프에서 조건을 제거 할 수 있어야합니다. 특히 :

void foo(const struct rect *r) { 
    for (int i = 0; i < r->width * r->height; i++) { 
    quux(); 
    } 
} 

컴파일러는 모든 것이 quux()r을 수정 알고,이 경우에 곱셈을 이동할 수 없습니다.

일반적으로 로컬 변수 만 루프에서 표현식을 들여 올 수 있습니다 (주소를 사용하지 않는다고 가정 할 때!). 구조체 멤버도 자격이 될 수 있지만, 컴파일러가 메모리의 모든 내용이 변경되었다고 생각할 수있는 많은 것들이 있습니다. 예를 들어, 거의 모든 포인터로 쓰거나, 사실상 모든 함수를 호출하는 경우가 있습니다. 따라서 지역 이외의 다른 지역을 사용하는 경우 최적화가 발생하지 않는다고 가정하는 것이 가장 좋습니다. 그래서가

  • 은 분명히 를 취할 것

    • 이 할 가독성을 다치게하지 않습니다 : 그것은 어느 경우

      말했다 즉, 일반적으로, 나는 단지 상태에서 잠재적으로 고가의 코드를 이동 적극적으로 권 해드립니다 매우 장시간 (예 : 네트워크 액세스)

    • 또는 프로파일 링에 핫스팟으로 표시됩니다.
  • +6

    예제에서 r은'const struct rect *'일 수 있으며, 컴파일러 * still *은 quux()가 별칭을 통해 데이터 멤버를 수정하지 않는다고 가정 할 수 없다는 점에 유의하십시오. 일반적으로 const는 모든 방식의 컴파일러 최적화를 활성화한다고 가정하지만 처음 생각할 때와 같이 간단하지는 않습니다. –

    +0

    @onebyone : 실제로. Restrict가 여기서 도움을 줄 수도 있습니다. – bdonlan

    +0

    그래, C99 컴파일러이기도하고 따라서 제한을 지원하는 C++ 컴파일러의 경우. 엄격한 앨리어싱 규칙은 "거의 모든 포인터에 대한 쓰기"를 돕지 만 "사실상 모든 함수 호출"과는 다릅니다. 인라인은 함수에 도움이됩니다. –