[c++] if (flag == 0) 또는 if (0 == flag) 중 어느 것이 더 빨리 실행됩니까?

인터뷰 질문 : 한 빨리 실행됩니다 if (flag==0)또는 if (0==flag)? 왜?



답변

나는 아직 정답을 보지 못했습니다 (그리고 이미 일부가 있습니다) 경고 : Nawaz는 사용자 정의 트랩을 지적했습니다 . 그리고 “가장 어리석은 질문”에 대해 서둘러 찬성 투표를 한 것을 후회합니다. 많은 사람들이 제대로 이해하지 못한 것 같고 컴파일러 최적화에 대한 좋은 토론의 여지를 제공합니다. 🙂

정답은:

flag유형 은 무엇입니까 ?

경우 여기서 flag실제로 사용자 정의 형식이다. 그런 다음 어떤 과부하 operator==가 선택 되었는지에 따라 다릅니다 . 물론 그것들이 대칭 적이 지 않다는 것은 어리석은 것처럼 보일 수 있지만, 그것은 확실히 허용되며, 이미 다른 학대를 보았습니다.

flag가 내장 된 경우 둘 다 동일한 속도를 가져야합니다.

에 대한 Wikipedia 기사 에서 x86나는 진술 에 대한 Jxx지침을 if기대할 것 JNZ입니다.

최적화가 꺼져 있어도 컴파일러가 그러한 명백한 최적화를 놓치는 것은 의심 스럽습니다. 이것은 Peephole Optimization 이 설계된 유형입니다 .

편집 : 다시 시작되었으므로 어셈블리를 추가해 보겠습니다 (LLVM 2.7 IR).

int regular(int c) {
  if (c == 0) { return 0; }
  return 1;
}

int yoda(int c) {
  if (0 == c) { return 0; }
  return 1;
}

define i32 @regular(i32 %c) nounwind readnone {
entry:
  %not. = icmp ne i32 %c, 0                       ; <i1> [#uses=1]
  %.0 = zext i1 %not. to i32                      ; <i32> [#uses=1]
  ret i32 %.0
}

define i32 @yoda(i32 %c) nounwind readnone {
entry:
  %not. = icmp ne i32 %c, 0                       ; <i1> [#uses=1]
  %.0 = zext i1 %not. to i32                      ; <i32> [#uses=1]
  ret i32 %.0
}

IR을 읽는 방법을 모르더라도 자명하다고 생각합니다.


답변

GCC 4.1.2를 사용하는 amd64에 대한 동일한 코드 :

        .loc 1 4 0  # int f = argc;
        movl    -20(%rbp), %eax
        movl    %eax, -4(%rbp)
        .loc 1 6 0 # if( f == 0 ) {
        cmpl    $0, -4(%rbp)
        jne     .L2
        .loc 1 7 0 # return 0;
        movl    $0, -36(%rbp)
        jmp     .L4
        .loc 1 8 0 # }
 .L2:
        .loc 1 10 0 # if( 0 == f ) {
        cmpl    $0, -4(%rbp)
        jne     .L5
        .loc 1 11 0 # return 1;
        movl    $1, -36(%rbp)
        jmp     .L4
        .loc 1 12 0 # }
 .L5:
        .loc 1 14 0 # return 2;
        movl    $2, -36(%rbp)
 .L4:
        movl    -36(%rbp), %eax
        .loc 1 15 0 # }
        leave
        ret


답변

버전에는 차이가 없습니다.

typeof 플래그가 사용자 정의 유형이 아니라 일부 내장 유형 이라고 가정하고 있습니다. Enum은 예외입니다! . enum을 내장 된 것처럼 취급 할 수 있습니다. 사실, 그것의 값은 내장형 중 하나입니다!

사용자 정의 유형 (제외 enum) 인 경우 대답은 전적으로 연산자를 오버로드 한 방법에 따라 달라집니다 ==. ==각 버전에 대해 하나씩 두 개의 함수를 정의 하여 오버로드 해야합니다!


답변

전혀 차이가 없습니다.

하지만 다음과 같이 할당 / 비교 오타 제거를 참조하여 인터뷰 질문에 답할 때 점수를 얻을 수 있습니다.

if (flag = 0)  // typo here
   {
   // code never executes
   }

if (0 = flag) // typo and syntactic error -> compiler complains
   {
   // ...
   }

예를 들어 C 컴파일러가 전자 ( flag = 0)의 경우 경고하는 것은 사실이지만 PHP, Perl 또는 Javascript 또는 <insert language here>.


답변

속도면에서 전혀 차이가 없습니다. 왜 있어야합니까?


답변

플래그가 사용자 정의 유형일 때 차이가 있습니다.

struct sInt
{
    sInt( int i ) : wrappedInt(i)
    {
        std::cout << "ctor called" << std::endl;
    }

    operator int()
    {
        std::cout << "operator int()" << std::endl;
        return wrappedInt;
    }

    bool operator==(int nComp)
    {
        std::cout << "bool operator==(int nComp)" << std::endl;
        return (nComp == wrappedInt);
    }

    int wrappedInt;
};

int
_tmain(int argc, _TCHAR* argv[])
{
    sInt s(0);

    //in this case this will probably be faster
    if ( 0 == s )
    {
        std::cout << "equal" << std::endl;
    }

    if ( s == 0 )
    {
        std::cout << "equal" << std::endl;
    }
}

첫 번째 경우 (0 == s)에서 변환 연산자가 호출되고 반환 된 결과가 0과 비교됩니다. 두 번째 경우에는 == 연산자가 호출됩니다.


답변

의심 스러울 때 그것을 벤치마킹하고 진실을 배우십시오.