자체 이니셜 라이저에서 변수 사용


22

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 에서 불확실한 값으로 변수를 직접 초기화 할 수 있는 특정 예외 가 있습니다 (불확실한 값을 사용하여 초기화 발생) ).xunsigned charunsigned char

따라서 이것만으로는 정의되지 않은 동작 T이 발생하지 않지만 서명되지 않은 좁은 문자 유형이 아닌 다른 유형 또는 std::byte예를 들어 int x = x;. 이러한 고려 사항은 C ++ 17과 그 이전에도 적용되었으며 하단의 관련 질문도 참조하십시오.

그러나 unsigned char x = x;현재 초안의 [basic.lifetime] / 7 은 다음과 같이 말합니다.

마찬가지로 객체의 수명이 시작되기 전에 [...] 값에 의존하지 않는 glvalue의 속성을 사용하여 잘 정의됩니다. 다음과 같은 경우 프로그램에 정의되지 않은 동작이 있습니다.

  • glvalue는 객체에 액세스하는 데 사용되거나

  • [...]

이것은 x예제에서의 값이 수명 기간 동안 만 사용될 수 있음을 의미하는 것 같습니다 .

[basic.lifetime] / 1의 말 :

[...]

T 유형의 객체 수명은 다음과 같은 경우에 시작됩니다.

  • [...] 그리고
  • 초기화 (있는 경우)가 완료되었습니다 (빈 초기화 포함) ([dcl.init]),

[...]

따라서 x의 수명은 초기화가 완료된 후에 만 ​​시작됩니다. 그러나 인용 된 예제에서 x의 값은 x초기화가 완료 되기 전에 사용 됩니다. 따라서 사용에는 정의되지 않은 동작이 있습니다.

내 분석이 정확합니까? 그렇다면 초기화와 같은 유사한 사용 전 사례에 영향을 미칩니 까?

int x = (x = 1);

내가 알 수있는 한 C ++ 17과 그 이전에 잘 정의되어 있습니까?


C ++ 17 (최종 초안)에서 시작하는 평생에 대한 두 번째 요구 사항은 다릅니다 .

  • 개체에 빈 공간이없는 초기화가 있으면 초기화가 완료됩니다.

xC ++ 17의 정의 (현재 초안의 것은 아님)에 의한 빈틈없는 초기화가 있기 때문에 , 위의 예제에서 초기화 프로그램에 액세스 할 때 수명이 이미 시작되었으므로 두 예제 모두 정의되지 않은 동작이 없었습니다. xC ++ 17의 수명으로 인해 .

C ++ 17 이전의 문구는 다시 다르지만 결과는 같습니다.


불확실한 값을 사용할 때 정의되지 않은 동작에 관한 질문은 다음과 같은 질문에서 다루었습니다.


@LanguageLawyer 나는 아직 아무도 대답하지 않았다면, 내가 정확하지 않다고 확신하지 않습니다. 다른 사람이 여기에 동의 할 경우 나중에 제출할 수도 있고 다른 사람이 내 앞에 올 수도 있지만 확실하지 않은 문제를 신고하고 싶지 않습니다.
호두

@LanguageLawyer : 작업 논문이 확실하게 잘못된 것을 말하면 편집상의 문제가 될 수 없습니다.
Davis Herring

1
단어는 P1358에 의해 변경됩니다 .
xskxzr

1
@xskxzr 맞습니다. 그 동안 LanguageLawyer도 편집 문제를 제기했습니다.이 문제 는 의도를 명확히하기 위해 CWG로 전달 된 것으로 보입니다.
호두

1
@ clockw0rk int x ^= x;은 구문 상 제대로 구성 되어 있지 않습니다. (즉, 당신도 초기화의 변수 정의를 가질 수 int x = x;는 UB 비록,) 또는 XOR 대입 표현 문 (즉 x ^= x;경우, 비록이 UB입니다 x유형 인 int기본 초기화 아니라 사전에 할당). 이 둘을 하나로 혼합 할 수 없습니다.
호두

답변:


8

이것은 편집 문제 로 개설되었습니다 . (내부) 토론을 위해 CWG로 전달되었습니다. 약 24 시간 후 문제를 전달한 사람 이 풀 요청작성 하여 예제가 UB임을 명확히하기 위해 수정했습니다.

이니셜 라이저가 수명 \ iref {basic.life} 외부에서 두 번째 \ tcode {x}에 액세스하기 때문에 두 번째 \ tcode {x}의 초기화에는 정의되지 않은 동작이 있습니다.

그 PR은 이후에 추가되었고 문제는 종결되었습니다. 따라서 명백한 해석 (수명이 시작되지 않은 객체에 액세스하여 발생하는 UB)이 의도 된 해석이라는 것이 분명해 보입니다. 이위원회의 의도가 나타납니다 이다 이러한 구조는 비 기능하기 위해, 표준의 비 규범 텍스트가이 내용을 반영하도록 갱신되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.