eval_order — 평가 순서

eval_order — 평가 순서 (Order of evaluation)

**평가 순서(order of evaluation)**는 표현식의 각 부분이 실행되는 순서를 뜻해요. C++에서 표현식의 어떤 부분의 평가 순서 — 함수 인자의 평가 순서를 포함해서 —는 (아래 나열한 예외를 제외하고) **불명시(unspecified)**예요.

컴파일러는 피연산자와 부분 표현식을 어떤 순서로든 평가할 수 있고, 같은 표현식을 다시 평가할 때 다른 순서를 선택할 수도 있어요.

출처: cppreference

본문

C++에는 왼쪽에서 오른쪽이나 오른쪽에서 왼쪽으로 평가한다는 개념이 없어요. 이것을 연산자의 좌결합/우결합(associativity)과 혼동하면 안 돼요. 표현식 a() + b() + c()operator+의 좌결합성 때문에 (a() + b()) + c()로 파싱되지만, 런타임에는 c()a()b()보다 먼저, 나중에, 또는 그 사이에 평가될 수 있어요.

#include <cstdio>

int a() { return std::puts("a"); }
int b() { return std::puts("b"); }
int c() { return std::puts("c"); }

void z(int, int, int) {}

int main()
{
    z(a(), b(), c());       // 출력의 6가지 순열 모두 허용됨
    return a() + b() + c(); // 출력의 6가지 순열 모두 허용됨
}

다만 다음은 정해진 순서로 평가돼요.

  • 단락 평가: &&, ||, 삼항(?:) 연산자의 왼쪽 피연산자는 오른쪽보다 먼저 평가돼요.
  • 콤마 연산자와 함수 호출의 피연산자 평가는 정해져 있어요.

그래서 이 코드는 문제가 있어요.

std::printf("%d %d", i++, i++);   // 인자 평가 순서 불명시 → 정의되지 않은 동작
v[i] = ++i;                       // 위험: i의 변경 순서가 불명시

변수 하나를 같은 표현식 안에서 읽고 쓰는 조작을 순서 없이 하면 정의되지 않은 동작(undefined behavior)이 돼요. 부작용이 있는 호출(특히 함수 인자)이 서로 얽히지 않도록 주의해야 해요.

더 알아보기 (Learn more)

cppreference