2010-02-12 2 views
8

잠시 동안 C++을 사용하지 않았습니다. 나는 자바 컴파일러에 의존하여 최적화를 수행했다.C++ for 루프에서 int 선언

C++에서 for 루프를 수행하는 가장 최적화 된 방법은 무엇입니까? 또는 moderm 컴파일러에서 모두 동일합니다. '옛날'에는 차이가있었습니다.

for (int i=1; i<=100; i++) 

또는

int i; 
for (i=1; i<=100; i++) 

또는

int i = 1; 
for (; i<=100; i++) 

그것은 C에서 동일합니까?

편집 : 좋아, 압도적 인 합의가 첫 번째 경우를 사용하고 원하는 경우 컴파일러는 그것으로 최적화 할 것입니다 때문에.

+6

이런 종류의 질문은 정말 나쁜 징조입니다 ... –

+0

+1이 질문에 단지 신화가 디버프 될 수 있습니다. – Andres

답변

12

나는이 같은 사소한 것들은 아마 컴파일러에 의해 최적화되어 있다고 말할 것이고, 당신은 그것에 대해 걱정할 필요가 없다. 첫 번째 옵션은 가장 읽기 쉽기 때문에이를 사용해야합니다.

EDIT : 루프 이니셜 라이저에서 변수를 선언하면 루프가 끝난 후에 변수가 선언되면 다른 대답이 추가됩니다.

+2

편집과 관련하여 이것은 컴파일러에 달려 있습니다. 루프가 끝난 후 변수가 존재하지 않는 컴파일러 (MSVC++ 6.0)가 적어도 하나는 보았습니다. –

+2

@Jeff 표준 호환 컴파일러는 _i_ for 루프의 범위를 제한하지만 MSVC++ 6.0과 같은 이전 컴파일러는 없습니다. 따라서 오래된 컴파일러를 사용한다면 조심해야 할 것입니다. 그러나 언어 표준에 따라 범위는 for 루프로 제한됩니다. 최근의 컴파일러는 이와 관련하여 올바르게 작동해야합니다. –

+0

MSVC에서 "if (0) {} else for"해킹이 올바른 동작을 얻는 데 사용될 수 있습니다. 아 예, 좋은 옛날 ... –

4

동일합니다. 컴파일러는 이것들을 같은 것으로 최적화합니다.

동일하지 않더라도 루프의 실제 본문과의 차이는 무시할 수 있습니다. 이와 같은 미세 최적화에 대해서는 걱정할 필요가 없습니다. 실제로 성능 차이가 있는지 확인하기 위해 성능 프로파일 링을하지 않는 한 마이크로 최적화를해서는 안됩니다.

3

속도면에서는 같습니다. 나중에 i를 사용하지 않으면 컴파일러가 최적화됩니다.

스타일 측면에서 - 나중에 루프를 정의 할 때 충돌하는 위험을 줄여주기 때문에 루프 구조에 정의를 넣을 수 있습니다.

9

차이점은 범위입니다. 다음 I의 범위는 루프에 대한 제한 때문에

for(int i = 1; i <= 100; ++i) 

일반적으로 바람직하다. for 루프 앞에 선언하면 for 루프가 완료된 후에도 계속 존재하며 다른 변수와 충돌 할 수 있습니다. for 루프에서만 사용한다면 더 이상 존재할 이유가 없습니다.

+0

일부 구형 컴파일러에서 i의 범위는 함수의 끝 부분입니다. int를 루프 밖으로 이동하면 다른 컴파일러에서 계속 잘 수행 할 수 있습니다. – EvilTeach

+0

@EvilTech 이전의 호환되지 않는 컴파일러 만 해당 문제가 발생합니다. 따라서, 여러분의 코드가 그런 컴파일러와 함께 사용될 가능성이 있다고 생각하지 않는다면, 나는 그것에 대해 걱정하지 않을 것입니다. 문제가있는 경우 for 루프 주위에 여분의 괄호 쌍을 넣으면 문제가 해결됩니다. –

1

마이크로 최적화에 대해 걱정하지 마시고 컴파일러에서 처리하도록하십시오. 가장 가독성이 높은 것을 고르십시오. for 초기화 문 내에서 변수를 선언하면 변수의 범위가 for (C++ 03 § 6.5.3 1)이되지만 컴파일러의 정확한 동작이 다를 수 있습니다 (일부는 사용자가 선택할 수 있음). 루프 외부의 코드에서 변수를 사용하는 경우 루프 외부에서 선언하십시오. 변수가 루프의 로컬 변수이면 이니셜 라이저에 선언하십시오.

-1

모두 동일합니다.

1

두 가지 주요 차이점은 이미 언급 한 바 있습니다.내가 MSVC++ 6을 사용하는 경우, 내가 루프 외부 범위에 여전히 알고

for (int i = 1; ...;...) 

로 루프 전에 선언하는 것처럼 당신이 당신의 컴파일러가 선언하는 int의 범위를 처리하는 방법을 알고 있어야합니다 . 이 동작은 VS2005와는 다르며 확인해야하지만 gcc의 마지막 버전을 사용했다고 생각합니다. 두 컴파일러 모두에서 해당 변수는 루프 내부에만있었습니다.

+0

VC++ 6에서 잘 알려진 버그입니다. 정말로 신경 쓰는 경우 for 루프를 다른 중괄호로 둘러 쌉니다. – jmucchiello

5

원래의 포스터에는 실제로 최적화 된 루프가 있다고 가정 해 봅시다. 그의 질문에 대한 답은 어떻게 경험적으로 파악할 수 있습니까?

gcc에는 적어도 '드물기는하지만'-S 스위치가 유용합니다. .c 파일의 어셈블리 코드 버전을 덤프하고 OP 포즈와 같은 질문에 대답하는 데 사용할 수 있습니다. 나는 간단한 프로그램 작성 :

int main() 
{ 
    int sum = 0; 

    for(int i=1;i<=10;++i) 
    { 
     sum = sum + i; 
    } 
    return sum; 
} 

을 그리고 실행 : gcc -O0 -std=c99 -S main.c를, 메인 프로그램의 어셈블리 버전을 생성. 당신은 무슨 일이 일어나고 있는지 알아 내기 위해 조립 전문가가 될 필요가 없습니다

movl $0, -8(%rbp) 
    movl $1, -4(%rbp) 
    jmp  .L2 
.L3: 
    movl -4(%rbp), %eax 
    addl %eax, -8(%rbp) 
    addl $1, -4(%rbp) 
.L2: 
    cmpl $10, -4(%rbp) 
    jle  .L3 

: 여기 (제거 보풀의 일부) main.s의 내용입니다. movl은 값을 이동하고, addl은 물건을 추가하고, cmpl은 비교하고, jle은 '미만이면 점프'를 의미하고, $는 상수를 의미합니다. 0을 무언가에로드하고 있습니다. 'sum'이어야하며, 1은 다른 것으로 들어가야합니다. - 아, 'i'! 우리가 10과 비교할 때 L2로 건너 뛰고, 추가를하기 위해 L3으로 건너 뜁니다. 비교를 위해 다시 L2로 내려갑니다. 산뜻한! for 루프.

변경 프로그램 :

int main() 
{ 
    int sum = 0; 
    int i=1; 
    for(;i<=10;++i) 
    { 
     sum = sum + i; 
    } 
    return sum; 
} 

다시 실행의 GCC 및 결과 어셈블리는 매우 유사합니다. 레코드 번호로 몇 가지 문제가 발생하므로 동일하지는 않지만 어셈블리가 동일하게 끝납니다. 마지막 사건과 같은 결과. 따라서 최적화가 없어도 코드는 거의 같습니다.

재미를 위해 gcc를 '-O0'대신 '-O3'으로 다시 실행하여 최적화를 활성화하고 .s 파일을 살펴보십시오.

main: 
movl $55, %eax 
ret 

GCC는 우리가 루프를하고 있던 파악하지만, 또한, 시간의 상수는 컴파일시에 우리를 위해 루프를 한 실행했다 '내가'와 '합'을 밖으로 내 던졌다 실현되지 답을 하드 코딩했습니다 - 55! 조금 빨라졌지만 빠릅니다.

이야기의 도덕? 코드가 깨끗하고 잘 설계되었는지 확인하는 데 시간을 투자하십시오. 가독성과 유지 보수성을위한 코드. 마운틴 이슬과 치토에 살고있는 사람들은 우리보다 훨씬 똑똑하고 우리를 위해 이러한 간단한 최적화 문제를 돌봐 왔습니다. 재미있어!

1
for(int i = 1; i <= 100; ++i) 

이것은 잘못입니다 ANSI C/C89를 제외하고 읽기 쉬운 것입니다.

관련 문제