[basic.scope.pdecl] / 1 du projet de norme C ++ 20 contenait l' exemple (non normatif) suivant dans une note (citation partielle d'avant la fusion de la demande de tirage 3580 , voir la réponse à cette question):
unsigned char x = x;
[...] x est initialisé avec sa propre valeur (indéterminée).
Cela a-t-il réellement un comportement bien défini en C ++ 20?
Généralement, l'auto-initialisation du formulaire T x = x;
a un comportement indéfini du fait que x
la valeur de 'est indéterminée avant la fin de l'initialisation. L'évaluation de valeurs indéterminées provoque généralement un comportement indéfini ( [basic.indent] / 2 ), mais il existe une exception spécifique dans [basic.indent] /2.3 qui permet d'initialiser directement une unsigned char
variable à partir d'une valeur l unsigned char
avec une valeur indéterminée (provoquant l'initialisation avec une valeur indéterminée) ).
Cela seul ne provoque donc pas de comportement indéfini, mais le serait pour d'autres types T
qui ne sont pas des types de caractères étroits non signés ou std::byte
, par exemple int x = x;
. Ces considérations s'appliquaient également en C ++ 17 et avant, voir également les questions liées en bas.
Cependant, même pour unsigned char x = x;
, le projet actuel [basic.lifetime] / 7 dit:
De même, avant que la durée de vie d'un objet ne commence [...], l'utilisation des propriétés de la valeur gl qui ne dépendent pas de sa valeur est bien définie. Le programme a un comportement indéfini si:
la glvalue est utilisée pour accéder à l'objet, ou
[...]
Cela semble impliquer que x
la valeur de dans l'exemple ne peut être utilisée que pendant sa durée de vie.
[basic.lifetime] / 1 dit:
[...]
La durée de vie d'un objet de type T commence lorsque:
- [...] et
- son initialisation (le cas échéant) est terminée (y compris l'initialisation vide) ([dcl.init]),
[...]
Ainsi, x
la durée de vie ne commence qu'une fois l'initialisation terminée. Mais dans l'exemple cité, x
la valeur est utilisée avant x
la fin de l'initialisation. Par conséquent, l'utilisation a un comportement indéfini.
Mon analyse est-elle correcte et, dans l'affirmative, affecte-t-elle des cas similaires d'utilisation avant l'initialisation tels que
int x = (x = 1);
qui, pour autant que je sache, étaient bien définies en C ++ 17 et avant?
Notez qu'en C ++ 17 (version finale), la deuxième exigence de durée de vie pour commencer était différente :
- si l'objet a une initialisation non vide, son initialisation est terminée,
Étant x
donné que l'initialisation serait vide par la définition de C ++ 17 (mais pas celle du projet actuel), sa durée de vie aurait déjà commencé lorsqu'elle est accessible dans l'initialiseur dans les exemples ci-dessus et donc dans les deux exemples, il n'y avait pas de comportement indéfini. en raison de la durée de vie de x
C ++ 17.
La formulation avant C ++ 17 est à nouveau différente, mais avec le même résultat.
La question ne concerne pas un comportement indéfini lors de l'utilisation de valeurs indéterminées, qui a été couvert par exemple dans les questions suivantes:
int x ^= x;
n'est pas bien formé syntaxiquement. Vous pouvez soit avoir une définition de variable avec initialiseur (c'est-à int x = x;
- dire , bien qu'il soit UB), soit une instruction d'expression d'affectation xor (c'est x ^= x;
-à- dire , bien qu'elle soit UB si elle x
est de type int
, a été initialisée par défaut et n'a pas été affectée à l'avance). Vous ne pouvez pas mélanger ces deux en un.