C ++ 20 표준 초안의 [basic.scope.pdecl] / 1 은 다음과 같은 (비 규범 적) 예제를 주 ( 풀 요청 3580 의 병합 이전의 부분 인용 ,이 질문에 대한 답변 참조)에 있습니다.
unsigned char x = x;
[...] x는 자체 (결정되지 않은) 값으로 초기화됩니다.
이것이 실제로 C ++ 20에서 잘 정의 된 동작을 가지고 있습니까?
일반적으로 양식의 자체 초기화는 초기화가 완료되기 전에 의 값이 결정 되지 않기T x = x;
때문에 정의되지 않은 동작을 합니다. 불확실한 값을 평가하면 일반적으로 정의되지 않은 동작 ( [basic.indent] / 2 )이 발생하지만 [basic.indent] /2.3 에는 lvalue 에서 불확실한 값으로 변수를 직접 초기화 할 수 있는 특정 예외 가 있습니다 (불확실한 값을 사용하여 초기화 발생) ).x
unsigned char
unsigned char
따라서 이것만으로는 정의되지 않은 동작 T
이 발생하지 않지만 서명되지 않은 좁은 문자 유형이 아닌 다른 유형 또는 std::byte
예를 들어 int x = x;
. 이러한 고려 사항은 C ++ 17과 그 이전에도 적용되었으며 하단의 관련 질문도 참조하십시오.
그러나 unsigned char x = x;
현재 초안의 [basic.lifetime] / 7 은 다음과 같이 말합니다.
마찬가지로 객체의 수명이 시작되기 전에 [...] 값에 의존하지 않는 glvalue의 속성을 사용하여 잘 정의됩니다. 다음과 같은 경우 프로그램에 정의되지 않은 동작이 있습니다.
glvalue는 객체에 액세스하는 데 사용되거나
[...]
이것은 x
예제에서의 값이 수명 기간 동안 만 사용될 수 있음을 의미하는 것 같습니다 .
[...]
T 유형의 객체 수명은 다음과 같은 경우에 시작됩니다.
- [...] 그리고
- 초기화 (있는 경우)가 완료되었습니다 (빈 초기화 포함) ([dcl.init]),
[...]
따라서 x
의 수명은 초기화가 완료된 후에 만 시작됩니다. 그러나 인용 된 예제에서 x
의 값은 x
초기화가 완료 되기 전에 사용 됩니다. 따라서 사용에는 정의되지 않은 동작이 있습니다.
내 분석이 정확합니까? 그렇다면 초기화와 같은 유사한 사용 전 사례에 영향을 미칩니 까?
int x = (x = 1);
내가 알 수있는 한 C ++ 17과 그 이전에 잘 정의되어 있습니까?
C ++ 17 (최종 초안)에서 시작하는 평생에 대한 두 번째 요구 사항은 다릅니다 .
- 개체에 빈 공간이없는 초기화가 있으면 초기화가 완료됩니다.
x
C ++ 17의 정의 (현재 초안의 것은 아님)에 의한 빈틈없는 초기화가 있기 때문에 , 위의 예제에서 초기화 프로그램에 액세스 할 때 수명이 이미 시작되었으므로 두 예제 모두 정의되지 않은 동작이 없었습니다. x
C ++ 17의 수명으로 인해 .
C ++ 17 이전의 문구는 다시 다르지만 결과는 같습니다.
불확실한 값을 사용할 때 정의되지 않은 동작에 관한 질문은 다음과 같은 질문에서 다루었습니다.
int x ^= x;
은 구문 상 제대로 구성 되어 있지 않습니다. (즉, 당신도 초기화의 변수 정의를 가질 수 int x = x;
는 UB 비록,) 또는 XOR 대입 표현 문 (즉 x ^= x;
경우, 비록이 UB입니다 x
유형 인 int
기본 초기화 아니라 사전에 할당). 이 둘을 하나로 혼합 할 수 없습니다.