programing

'for' 루프 내에서의 포스트 인크리먼트와 프리 인크리먼트에서도 동일한 출력이 생성됩니다.

nicescript 2022. 8. 9. 22:13
반응형

'for' 루프 내에서의 포스트 인크리먼트와 프리 인크리먼트에서도 동일한 출력이 생성됩니다.

하나는 포스트 인크리먼트, 다른 하나는 프리 인크리먼트를 사용해도 루프의 결과는 동일합니다.

코드는 다음과 같습니다.

for(i=0; i<5; i++) {
    printf("%d", i);
}

for(i=0; i<5; ++i) {
    printf("%d", i);
}

양쪽 'for' 루프에 대해 동일한 출력을 얻을 수 있습니다.내가 뭘 빼놓았나요?

i++ ★★★★★★★★★★★★★★★★★」++i의 " " " "i두 경우 모두 동일합니다.사전 및 사후 증가 간의 차이는 표현식 자체를 평가한 결과입니다.

++i increi새로운 가치로 평가합니다.i.

i++ 로 평가하다i및, " " "i.

for 루프에서는 이것이 문제가 되지 않는 이유는 컨트롤 플로우가 대략 다음과 같이 동작하기 때문입니다.

  1. 상태를 시험하다
  2. 거짓일 경우 종료합니다.
  3. 그것이 사실이라면, 본문을 처형하라.
  4. 증가 단계를 실행하다

(1)과 (4)는 분리되므로 사전 또는 사후 증가를 사용할 수 있습니다.

간단해요.의 「 」for '루프'와 동등합니다.

int i = 0;
while(i < 5) {
    printf("%d", i);
    i++;
}

그리고.

int i = 0;
while(i < 5) {
    printf("%d", i);
    ++i;
}

은 「」으로 되어 있는 것에 해 주세요.i++; ★★★★★★★★★★★★★★★★★」++i;에서 동일한 . 다 .i(1개씩 변환)하기 때문에 이들 루프의 동작에 동일한 영향을 미칩니다.

루프가 다음과 같이 고쳐지면 차이가 있음을 주의해 주십시오.

int i = 0;
int j = i;
while(j < 5) {
    printf("%d", i);
    j = ++i;
}

int i = 0;
int j = i;
while(j < 5) {
    printf("%d", i);
    j = i++;
}

는 코드 첫 코드 '''가ji 후는)))i 번째, 즉 및 "Code"의 두 에서는 "Code "Code "는 "Code"의 두 번째 블록에서 합니다.ji이치노

코드 결과는 동일합니다.그 이유는 2개의 증분 연산이 2개의 서로 다른 함수 호출로 간주될 수 있기 때문입니다.두 함수에 따라 변수가 증가하며 반환값만 다릅니다.이 경우 반환값은 그냥 버려집니다.즉, 출력에 구별 가능한 차이는 없습니다.

하지만 후드 아래에는 차이가 있습니다.포스트 인크리먼트i++원래 값을 저장하는 임시 변수를 생성해야 합니다.i그러면 인크리먼트가 실행되고 일시 변수가 반환됩니다. 인크리먼트 「」++i임시 변수는 생성되지 않습니다.물론,, 적절한 할 수 .int단, 반복기처럼 복잡한 클래스에서는 ++-private가 과부하된다는 점에 유의하십시오.과부하된 두 메서드는 서로 다른 연산(예를 들어 stdout에 "Hey, I'm pre-increment!"를 출력하고 싶을 수 있음)을 가지고 있기 때문에 컴파일러는 반환값을 사용하지 않을 때 메서드가 동일한지 여부를 판단할 수 없습니다(기본적으로 이러한 컴파일러는 해결할 수 없는 정지 문제를 해결하기 때문에).따라서 더 비싼 메서드를 사용해야 합니다.포스트 인크리먼트버전(기입하는 경우)myiterator++.

사전 증가를 해야 하는 세 가지 이유는 다음과 같습니다.

  1. 변수/개체에 오버로드된 사후 증분 메서드(템플릿 함수 등)가 있는지 여부를 고려하여 다르게 취급할 필요가 없습니다(또는 다른 취급을 잊어버릴 수도 있습니다).
  2. 일관된 코드가 더 보기 좋습니다.
  3. "왜 미리 증가시키느냐"는 질문을 받으면 컴파일러 최적화의 중단 문제와 이론적 한계에 대해 설명할 기회가 주어집니다.:)

이것은 제가 가장 좋아하는 인터뷰 질문 중 하나입니다.정답을 먼저 설명하고 제가 왜 이 질문을 좋아하는지 말씀드리겠습니다.

솔루션:

정답은 두 스니펫 모두 0부터 4까지의 숫자를 인쇄하는 것입니다.은, 「」가for()으로는 루는는 loop loop loop a a a에 해당합니다.while() 디세이블로그:

for (INITIALIZER; CONDITION; OPERATION) {
    do_stuff();
}

기입 가능:

INITIALIZER;
while(CONDITION) {
    do_stuff();
    OPERATION;
}

OPERATION은 항상 루프의 맨 아래에서 수행됨을 알 수 있습니다.이 형식에서는, 다음과 같은 것을 명확히 할 필요가 있습니다.i++ ★★★★★★★★★★★★★★★★★」++i같은 효과가 있을 것이다: 둘 다 증가하게 될 것이다.i결과를 무시합니다.「」의 값.i는 다음 반복이 시작될 때까지 루프 상부에서 테스트되지 않습니다.


편집: Jason이 지적해 주셔서 감사합니다.for()로로 합니다.while()루프가 제어문을 포함하는 경우 등가성은 유지되지 않습니다(예:continue을하는 것입니다.OPERATIONwhile() 루우프OPERATION항상 다음 반복 직전에 실행됩니다.for()loopsyslog.syslog..syslog.


왜 좋은 인터뷰 질문인가

우선, 후보자가 바로 정답을 말하면 1, 2분이면 되기 때문에 바로 다음 문제로 넘어갈 수 있습니다.

그런데 의외로 많은 후보자가 인크리먼트 후의 루프는 0부터4까지의 숫자를 인쇄하고, 인크리먼트 전의 루프는 0부터5까지 또는 1~5까지 인쇄한다고 합니다. 증가 를 정확하게하지만, 증가 전과 증가 후의 알고 .for()loopsyslog.syslog..syslog.

때는 '다'를 사용해서.while()그리고 이것은 정말 그들의 사고 과정을 잘 알 수 있게 해준다.하는지, 내가 돌아가는지 을 제기할 때 알고 싶다.나는 그들이 어떤 문제에 어떻게 접근하는지, 그리고 내가 그들의 세상이 어떻게 돌아가는지에 대해 의문을 제기했을 때 그들이 어떻게 대처하는지 알고 싶다.

이 시점에서 대부분의 응시자들은 자신의 오류를 깨닫고 정답을 찾는다. 그의 하다가 번역 for()while()흥미로운 인터뷰가 되었지만, 우리는 제안을 하지 않았다!

도움이 됐으면 좋겠네요!

i++, ++i 모두 printf(%d, i) 실행 후 매번 실행되므로 차이가 없다.

어느 경우든 루프의 본문 뒤에 증가하기 때문에 루프의 계산에는 영향을 주지 않습니다.컴파일러가 우둔한 경우에는 (보통 나중에 사용하기 위해 pre 의 복사본을 보관해야 하기 때문에) post-increment를 사용하는 것이 조금 덜 효율적일 수 있지만, 이 경우 어떤 차이도 최적화되지 않을까 생각합니다.

기본적으로 할당, 테스트 및 브랜치명령어 세트로 변환되는 for 루프의 실장 방법을 생각하면 편리할 수 있습니다.의사 코드의 프리 인크리먼트는 다음과 같습니다.

      set i = 0
test: if i >= 5 goto done
      call printf,"%d",i
      set i = i + 1
      goto test
done: nop

포스트 인크리먼트에는 적어도 다른 단계가 있습니다만, 최적화로 해소하는 것은 매우 간단합니다.

      set i = 0
test: if i >= 5 goto done
      call printf,"%d",i
      set j = i   // store value of i for later increment
      set i = j + 1  // oops, we're incrementing right-away
      goto test
done: nop

다음과 같은 경우에는 차이가 있습니다.

int main()
{
  for(int i(0); i<2; printf("i = post increment in loop %d\n", i++))
  {
    cout << "inside post incement = " << i << endl;
  }


  for(int i(0); i<2; printf("i = pre increment in loop %d\n",++i))
  {
    cout << "inside pre incement = " << i << endl;
  }

  return 0;
}

그 결과:

내부 포스트 인스톨 =

i = 루프 0의 사후 증가

내부 포스트 인스톨 = 1

i = 루프 1의 사후 증가

두 번째 루프:

내부 프리 인스톨 = 0

i = 루프 1의 사전 증가

내부 프리 인스톨 = 1

i = 루프 2의 사전 증가

이렇게 쓰면 문제가 됩니다.

for(i=0; i<5; i=j++) {
    printf("%d",i);
}

다음과 같이 쓴 경우보다 한 번 더 반복합니까?

for(i=0; i<5; i=++j) {
    printf("%d",i);
}

컴파일러 번역

for (a; b; c)
{
    ...
}

로.

a;
while(b)
{
    ...
 end:
    c;
}

따라서 고객님의 경우(사후/사전 증가)는 문제가 되지 않습니다.

편집: 속행은 단순히 다음으로 대체됩니다.goto end;

구글의 답변은 이쪽에서 보실 수 있습니다.http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Preincrement_and_Predecrement

요점은 단순한 오브젝트에는 차이가 없지만 반복기 및 기타 템플릿오브젝트에는 프리 인크리먼트를 사용해야 한다는 것입니다.

편집:

단순한 유형을 사용하기 때문에 차이가 없습니다.따라서 부작용이 없고 루프 본문 후에 사후 또는 사전 증분이 실행되므로 루프 본문의 값에 영향을 주지 않습니다.

이러한 루프에서 확인할 수 있습니다.

for (int i = 0; i < 5; cout << "we still not incremented here: " << i << endl, i++)
{
    cout << "inside loop body: " << i << endl;
}

네, 두 가지 출력 모두 정확하게 동일합니다.왜 그들이 당신에게 다른 결과를 제공해야 한다고 생각합니까?

다음과 같은 경우 증가 후 또는 증가 전 문제가 발생합니다.

int j = ++i;
int k = i++;
f(i++);
g(++i);

여기서 인수를 할당하거나 전달하여 값을 지정합니다. 다 안요.for루프만 증가합니다.★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★!

for construct의 세 번째 문은 실행되었을 뿐 평가된 값은 폐기되고 처리되지 않습니다.
평가된 값이 폐기되면 사전 및 사후 증분이 동일합니다.
하다

언급URL : https://stackoverflow.com/questions/4706199/post-increment-and-pre-increment-within-a-for-loop-produce-same-output

반응형