Y a-t-il une bonne raison pour que operator =
ne soit pas un point de séquence? À la fois en C et C++.Une bonne raison pour laquelle l'opérateur d'affectation n'est pas un point de séquence?
J'ai du mal à penser à un contre-exemple.
Y a-t-il une bonne raison pour que operator =
ne soit pas un point de séquence? À la fois en C et C++.Une bonne raison pour laquelle l'opérateur d'affectation n'est pas un point de séquence?
J'ai du mal à penser à un contre-exemple.
Sur demande:
En général, les choses ont besoin d'une raison d'être un point de séquence. Ils n'ont pas besoin d'une raison pas pour être un point de séquence; c'est le défaut.
Par exemple, &&
doit être un point de séquence en raison du comportement court-circuit: si le côté gauche est fausse, la droite ne doit pas être évaluée. (Il ne s'agit pas seulement d'optimisation, le côté droit peut avoir des effets secondaires, et/ou dépend du fait que le côté gauche est vrai, comme dans ptr && ptr->data
.) Par conséquent, le côté gauche doit être évalué en premier, avant le côté droit. côté-main, afin de voir si le côté droit devrait être évalué du tout.
Cette raison n'existe pas pour =
car, bien qu'il y ait "évaluation" à faire pour les deux côtés (bien qu'il y ait différentes restrictions sur ce qui peut apparaître des deux côtés: le côté gauche doit être une lvalue - le l
ne signifie pas "à gauche", btw, il signifie "emplacement", comme dans l'emplacement en mémoire - nous ne pouvons pas attribuer à un temporaire ou un littéral), peu importe quel côté est évalué en premier - aussi longtemps comme les deux côtés sont évalués avant l'affectation réelle.
+1, mais '=' n'étant pas un point de séquence m'a mordu une fois: j'avais 'myArray [i ++] =
IIRC et FWIW, Java fournit plus de garanties ici :) –
Le comportement de court-circuit par lui-même ne nécessiterait pas de point de séquence. Une expression comme '(((ch = * x ++)! = 0) && (* y ++ = ch))' pourrait, * sauf pour l'exigence explicite que && impose un point de séquence *, retarder l'incrément de x jusqu'à la fin de l'exécution de la deuxième partie de l'expression, puisque le compilateur pourrait déterminer avant d'incrémenter x si l'opérande gauche de '&&' serait évalué à zéro. En pratique, il est peu probable que les réarrangements de code interdits par le point de séquence soient utiles, mais dans certains cas théoriques, ils pourraient l'être. – supercat
C'est (sorte de). L'opérateur = (qui peut être défini par l'ingénieur (alias l'opérateur défini par l'utilisateur = pour les types de classe)) n'est que du sucre syntaxique pour un appel de fonction. En conséquence, il a la même sémantique "point de séquence" qu'un appel de fonction.
Si nous prenons à propos de types intégrés alors je pense que c'est une bonne chose.
Vous ne voulez pas introduire trop de points de séquence car cela entrave les optimisations.
Il s'agit uniquement de sucre syntaxique pour un appel de fonction pour des classes définies par l'utilisateur en C++. Bien que vous l'ayez sous-entendu, ce n'est pas clair du tout comme vous l'avez dit. –
'' sémantique des points de séquence '' qui ne sont pas particulièrement utiles, car - les arguments de 'operator =' seront les LHS et RHS du signe '=', et les appels de fonctions n'imposent pas d'ordre à l'évaluation de leurs arguments - juste l'évaluation de la fonction elle-même est un point de séquence. –
Il existe de nombreuses raisons pour ne pas exiger que l'un des côtés soit évalué avant l'autre. Une question plus intéressante est de savoir si l'évaluation des deux côtés, complète avec des effets secondaires, devrait être exigée avant que l'opérateur d'affectation ne fasse quoi que ce soit. Je suggérerais qu'une telle exigence soulagerait certaines restrictions d'aliasing mais dans certains cas nécessiterait plus de travail pour un compilateur. Par exemple, supposons que "foo" et "bar" sont des pointeurs vers de grandes structures dont les adresses se chevaucheraient. L'instruction "* foo = * bar;" représenterait un comportement indéfini selon la norme actuelle. S'il y avait un point de séquence entre l'évaluation des opérandes et l'assignation, une telle déclaration serait garantie de "fonctionner". Une telle garantie nécessiterait plus de complexité pour l'opérateur d'affectation, exigeant un code plus grand et plus lent même si, en pratique, les pointeurs ne se chevaucheront jamais.
Exemple:
unsigned char foo[100]; typedef struct {int x, int y;} POINT; POINT *p1 = (POINT*)foo; POINT *p2 = (POINT*)(&(p1->y));
Compte tenu des déclarations ci-dessus, je pense que les déclarations suivantes ont les comportements strictement définis indiqués et ne comportent aucun comportement non défini.
p1->y = somevalue; // Sets p2->x to somevalue p2->x = somevalue; // Sets p1->y to somevalue *p1 = mystruct; // Sets p2->x to mystruct.y *p2 = mystruct; // Sets p1->x to mystruct.x
Voici deux déclarations, cependant, impliquerait un comportement non défini:
*p1 = *p2; *p2 = *p1;
S'il y avait un point de séquence au signe égal, un compilateur devrait soit comparer p1 et p2, ou bien Copiez l'opérande source dans un emplacement temporaire, puis copiez-le dans la destination. La norme, cependant, indique clairement que les deux énoncés ci-dessus sont tous deux considérés comme des comportements non définis. La norme exige que les compilateurs génèrent du code qui fonctionne correctement lors de la copie d'une structure dans une structure qui ne se chevauche pas, mais n'impose aucune restriction à ce que les compilateurs peuvent faire si les structures se chevauchent. Un compilateur qui permettrait au processeur dans une boucle d'envoyer "Règles de Frink!" chaque socket TCP ouverte ne violerait pas la norme en faisant ainsi.
"grandes structures dont les adresses se chevauchent._" pouvez-vous donner un exemple? – curiousguy
Vous avez obtenu cette phrase "règles de froncement" de l'épisode Homer 3D de "The Simpsons", n'est-ce pas? – ninjalj
@curiousguy: Voir l'exemple. – supercat
Cela nécessiterait que le compilateur calcule le LHS avant le RHS. Pourquoi voudriez-vous créer ce genre de restriction? –
'a = b = c = 0;' – pmg
En général, les choses ont besoin d'être ** un ** point de séquence. Ils n'ont pas besoin d'une raison ** pas ** pour être un point de séquence; c'est le défaut. –