나는 평가 위반 순서에 대해 읽고 있었고 , 그들은 나를 당황스럽게하는 예를 제시합니다.
1) 스칼라 객체의 부작용이 동일한 스칼라 객체의 다른 부작용에 비해 순서가 맞지 않으면 동작이 정의되지 않습니다.
// snip f(i = -1, i = -1); // undefined behavior
이러한 맥락에서, i
A는 스칼라 객체 명백하게 수단
산술 유형 (3.9.1), 열거 유형, 포인터 유형, 멤버 유형에 대한 포인터 (3.9.2), std :: nullptr_t 및 이러한 유형의 cv 규정 버전 (3.9.3)을 통칭하여 스칼라 유형이라고합니다.
이 경우 진술이 어떻게 모호한 지 알 수 없습니다. 첫 번째 또는 두 번째 인수가 먼저 평가되는지 여부에 관계없이로 i
끝나고 -1
두 인수도 모두 같습니다 -1
.
누군가가 명확히 할 수 있습니까?
최신 정보
나는 모든 토론에 정말 감사합니다. 지금까지 나는 @harmic의 대답을 좋아 합니다. 왜냐하면이 문장을 정의하는 데 따르는 함정과 복잡성이 언뜻보기에 눈에 띄게 보이지만 복잡합니다. @ acheong87 은 참조를 사용할 때 발생하는 몇 가지 문제를 지적하지만이 질문의 순서가없는 부작용 측면과 직각이라고 생각합니다.
요약
이 질문에 많은 관심을 기울 였으므로 주요 요점 / 답변을 요약하겠습니다. 먼저, "왜"가 "무슨 원인 ", "무슨 이유 ", "무엇을 목적으로 " 와 밀접한 관련이 있지만 미묘하게 다른 의미를 가질 수 있다는 점에 대해 약간의 왜곡이 있습니다 . 나는 그들이 왜 "왜"라는 의미로 대답을 그룹화 할 것입니다.
어떤 원인으로
주요 대답은 여기에서 유래 폴 드레이퍼 와, 마틴 J는 광범위한 답변으로 유사하지만 기여. 폴 드레이퍼의 대답은
동작이 무엇인지 정의되어 있지 않기 때문에 정의되지 않은 동작입니다.
그 대답은 C ++ 표준이 말하는 것을 설명 할 때 전반적으로 매우 좋습니다. 또한 같은 UB 일부 관련 사건을 해결 f(++i, ++i);
하고 f(i=1, i=-1);
. 첫 번째 관련 사례에서 첫 번째 인수가 i+1
두 번째 i+2
인지 아니면 두 번째 또는 그 반대인지 명확하지 않습니다 . 두 번째로, i
함수 호출 후 1 또는 -1이어야하는지 명확하지 않습니다 . 이 두 경우 모두 다음 규칙에 속하기 때문에 UB입니다.
스칼라 객체의 부작용이 동일한 스칼라 객체의 다른 부작용에 비해 순서가 맞지 않으면 동작이 정의되지 않습니다.
따라서 f(i=-1, i=-1)
프로그래머의 의도가 (IMHO) 명백하고 모호하지 않더라도 동일한 규칙에 속하기 때문에 UB이기도합니다.
폴 드레이퍼는 또한 그의 결론에서
동작을 정의했을 수 있습니까? 예. 정의 되었습니까? 아니.
"무슨 이유 / 목적이 f(i=-1, i=-1)
정의되지 않은 행동 으로 남게 되었습니까?"
어떤 이유로 / 목적으로
C ++ 표준에는 약간의 감독 (심지어 부주의 할 수 있음)이 있지만, 많은 누락이 적절하고 합리적인 목적으로 사용됩니다. 목적이 종종 "컴파일러 작성기의 작업을 더 쉽게"만들거나 "더 빠른 코드"라는 것을 알고 있지만 , UB로 떠날만한 충분한 이유가 있는지에 대해 주로 관심이있었습니다 f(i=-1, i=-1)
.
harmic 과 supercat 은 UB 의 이유 를 제공하는 주요 답변을 제공합니다 . Harmic은 표면적으로 원자 할당 작업을 여러 기계 명령어로 분리 할 수있는 최적화 컴파일러가 최적의 속도를 위해 해당 명령어를 추가로 인터리브 할 수 있다고 지적합니다. 이것은 매우 놀라운 결과로 이어질 수 i
있습니다. 그의 시나리오에서 -2로 끝납니다! 따라서 고조파 는 연산에 순서가 지정되지 않은 경우 변수에 동일한 값 을 두 번 이상 할당하면 어떻게 악영향을 미칠 수 있는지 보여줍니다 .
supercat은 f(i=-1, i=-1)
해야 할 일 을하려고하는 함정에 대한 관련 설명을 제공합니다 . 그는 일부 아키텍처에서는 동일한 메모리 주소에 대한 여러 동시 쓰기에 대한 엄격한 제한이 있다고 지적합니다. 우리가보다 사소한 것을 다루는 경우 컴파일러는 이것을 잡기가 어려울 수 있습니다 f(i=-1, i=-1)
.
davidf 는 또한 하모닉 과 매우 유사한 인터리빙 지침의 예를 제공합니다.
각 고조파, supercat 및 davidf의 예는 다소 고안되었지만, 함께 모아서 f(i=-1, i=-1)
정의되지 않은 행동을해야하는 확실한 이유를 제공합니다 .
Paul Draper의 답변이 "원인"부분을 더 잘 다루었음에도 불구하고, 왜 모든 의미를 다루는 데 최선을 다했기 때문에 harmic의 답변을 받아 들였습니다.
다른 답변들
JohnB는 (일반 스칼라 대신) 오버로드 된 할당 연산자를 고려하면 문제가 발생할 수 있다고 지적합니다.
f(i-1, i = -1)
있습니다.
std::nullptr_t
및 이러한 유형의 cv 규정 버전 (3.9.3)을 통칭하여 스칼라 유형 이라고 합니다 . "