평가 순서에 관한 표준 초안 의이 부분 이 적절 하다고 생각합니다 .
1.9 프로그램 실행
...
- 언급 된 경우를 제외하고 개별 연산자의 피연산자 및 개별 식의 하위 식에 대한 평가는 순서가 지정되지 않습니다. 연산자의 피연산자의 값 계산은 연산자 결과의 값 계산 전에 순서가 지정됩니다. 스칼라 객체에 대한 부작용이 동일한 스칼라 객체에 대한 다른 부작용 또는 동일한 스칼라 객체의 값을 사용하는 값 계산과 관련하여 순서가 지정되지 않고 잠재적으로 동시 적이 지 않은 경우 동작이 정의되지 않습니다.
그리고 또한:
5.2.2 함수 호출
...
- [참고 : 접미사 식과 인수의 평가는 모두 서로에 대해 순서가 지정되지 않습니다. 인수 평가의 모든 부작용은 함수가 입력되기 전에 순서가 지정됩니다 — 끝 참고]
따라서 라인의 c.meth1(&nu).meth2(nu);
경우 최종 호출에 대한 함수 호출 연산자의 관점에서 연산자에서 무슨 일이 발생하는지 고려 meth2
하여 접미사 표현식과 인수로의 분석을 명확하게 볼 수 있습니다 nu
.
operator()(c.meth1(&nu).meth2, nu);
최종 함수 호출 (즉, 후위 식 및 ) 에 대한 후위 식 및 인수 의 평가는 위 의 함수 호출 규칙에 따라 서로에 대해 순서 가 지정 되지 않습니다 . 따라서 스칼라 객체에 대한 접미사 표현식 계산의 부작용 은 함수 호출 이전 의 인수 평가와 관련하여 순서가 지정되지 않습니다. 위 의 프로그램 실행 규칙에 따르면 이것은 정의되지 않은 동작입니다.c.meth1(&nu).meth2
nu
ar
nu
meth2
즉, 컴파일러가 호출 후 호출에 대한 nu
인수 를 평가할 필요가 없습니다. 즉, meth2
호출 meth1
에 영향을 meth1
미치는 부작용이 없다고 가정 할 수 있습니다 .nu
. 평가에 .
위에서 생성 된 어셈블리 코드는 main
함수에 다음 시퀀스를 포함합니다 .
- 변하기 쉬운
nu
는 스택에 할당되고 0으로 초기화됩니다.
- 레지스터 (
ebx
제 경우)는 다음 값의 사본을받습니다.nu
- 의 주소
nu
및c
매개 변수 레지스터에로드됩니다.
meth1
불린다
- 반환 값 레지스터와 이전에 캐시 된 값 의
nu
에서ebx
레지스터 파라미터 레지스터에로드
meth2
불린다
중요하게도 위의 5 단계에서 컴파일러는 nu
2 단계 의 캐시 된 값을 에 대한 함수 호출에서 재사용 할 수 있습니다 meth2
. 여기서는 작동중인 '정의되지 않은 동작' nu
호출에 의해 변경되었을 수 있는 가능성을 무시합니다 meth1
.
참고 : 이 답변은 원래 형식에서 실질적으로 변경되었습니다. 마지막 함수 호출 전에 순서가 지정되지 않은 피연산자 계산의 부작용에 대한 초기 설명은 정확하지 않기 때문입니다. 문제는 피연산자 자체의 계산이 불확실하게 배열된다는 사실입니다.