39 votes

Ce comportement de code est-il défini?

Que fait le code suivant imprimer à la console?

map<int,int> m;
m[0] = m.size();
printf("%d", m[0]);

Réponses possibles:

  1. Le comportement du code n'est pas défini car il n'est pas défini quel énoncé m[0] ou m.size() est exécuté en premier par le compilateur. Donc, elle peut imprimer 1 ainsi que 0.
  2. Il imprime 0 parce que le côté droit de l'opérateur d'affectation est exécuté en premier.
  3. Il imprime 1 parce que l' operator[] a la priorité la plus élevée de l'énoncé complet m[0] = m.size(). De ce fait, la séquence d'événements suivante se produit:

    • m[0] crée un nouvel élément dans la carte
    • m.size() est appelée, qui est maintenant en 1
    • m[0] est affectée précédemment retourné (par m.size()) 1
  4. La vraie réponse?, qui est l'inconnu pour moi^^

Merci d'avance pour vos réponses...
Woltan

17voto

Steve Jessop Points 166970

Je crois qu'il est indéterminé si 0 ou 1 est stocké dans m[0], mais ce n'est pas un comportement indéfini.

La LHS et RHS peuvent se produire dans l'ordre, mais ils sont tous les deux appels de la fonction, de sorte qu'ils ont tous les deux un point de séquence du début à la fin. Il n'y a pas de danger de les deux d'entre eux, collectivement, l'accès à l'objet même sans l'intermédiaire d'un point de séquence.

La cession est effective int affectation, pas un appel de fonction associée à la séquence de points, depuis operator[] retours T&. C'est brièvement inquiétant, mais ce n'est pas la modification d'un objet qui est accessible de n'importe où ailleurs dans la présente déclaration, de sorte que c'est aussi la sécurité. Il est accessible au sein de operator[], bien sûr, où il est initialisé, mais qui se produit avant la séquence de point sur le retour de operator[], donc c'est OK. Si ce n'était pas, m[0] = 0; serait undefined!

Cependant, l'ordre d'évaluation des opérandes d' operator= n'est pas spécifiée par la norme, de sorte que le résultat de l'appel d' size() peut être 0 ou 1, selon laquelle l'ordre se produit.

Ce qui suit est un comportement indéfini, si. Il ne fait pas les appels de fonction et donc il n'y a rien pour empêcher size accès (sur la DROITE) et modifiée (LHS) sans l'intermédiaire d'un point de séquence:

int values[1];
int size = 0;

(++size, values[0] = 0) = size;
/*     fake m[0]     */  /* fake m.size() */

2voto

Konrad Rudolph Points 231505

Il n'y a pas de point de séquence entre l'appel à operator [] et l'appel à clear dans cette instruction. Par conséquent, le comportement doit être indéfini.

2voto

Damon Points 26437

Il fait imprimer 1, et sans lever un avertissement (!) En utilisant gcc. Il devrait émettre un avertissement car il n’est pas défini.

La classe de priorité des deux operator[] et operator. est 2 alors que la classe de priorité de operator= est 16.
Cela signifie qu'il est bien défini que m[0] et m.size() seront exécutés avant l'affectation. Cependant, il n'est pas défini lequel s'exécute en premier.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X