Vous spécifiquement référence à la C++11, donc je vais répondre avec le C++11 réponse. Il est, cependant, très proche du C++03 répondre, mais la définition de la séquence est différente.
C++11 définit un séquencée avant la relation entre les évaluations sur un seul thread. Il est non symétrique, transitive et de pair-wise. Si certains d'évaluation A n'est pas séquencée avant que certains d'évaluation B et B est également pas séquencée avant de Un, puis deux évaluations sont séquencé.
L'évaluation d'une expression comprend à la fois les calculs de la valeur (la valeur d'une expression) et d'effets secondaires. Un exemple d'un effet secondaire est la modification d'un objet, qui est le plus important pour répondre à la question. D'autres choses comptent aussi comme des effets secondaires. Si un effet secondaire est séquencé par rapport à un autre effet secondaire ou de la valeur de calcul sur le même objet, alors votre programme a un comportement indéterminé.
Donc, c'est la mise en place. La première règle importante est:
Chaque valeur de calcul et des effets secondaires associés avec une pleine expression est séquencée avant chaque calcul de la valeur et des effets secondaires associés à la prochaine pleine expression à évaluer.
Ainsi, toute pleine expression est pleinement évalués avant la prochaine pleine expression. Dans votre question, nous sommes seulement à faire avec une pleine expression, à savoir l' i = v[i++]
, de sorte que nous n'avons pas besoin de s'inquiéter à ce sujet. La prochaine règle importante est:
Sauf indication contraire, l'évaluation des opérandes des opérateurs individuels et des sous-expressions des expressions individuelles sont séquencé.
Cela signifie que, en a + b
, par exemple, l'évaluation de l' a
et b
sont non séquencés (ils peuvent être évalués dans n'importe quel ordre). Maintenant, pour notre dernière règle importante:
La valeur des calculs des opérandes d'un opérateur sont séquencée avant de la valeur de calcul du résultat de l'opérateur.
Donc, pour a + b
, séquencée avant de les relations peuvent être représentées par un arbre où une flèche représente le séquencée avant la relation:
a + b (value computation)
^ ^
| |
a b (value computation)
Si les deux évaluations se produire dans les branches distinctes de l'arbre, ils sont non, si cet arbre montre que les évaluations de l' a
et b
sont non les uns par rapport aux autres.
Maintenant, laissez-nous faire la même chose pour votre i = v[i++]
exemple. Nous utilisons le fait que l' v[i++]
est équivalent à *(v + (i++))
. Nous utilisons aussi des connaissances supplémentaires sur le séquençage de postfix incrément:
La valeur de calcul de l' ++
expression est séquencée avant la modification de l'opérande de l'objet.
Nous voici donc (un nœud de l'arbre est d'une valeur de calcul, sauf si spécifié comme un effet secondaire):
i = v[i++]
^ ^
| |
i★ v[i++] = *(v + (i++))
^
|
v + (i++)
^ ^
| |
v ++ (side effect on i)★
^
|
i
Ici, vous pouvez voir que le côté effet sur i
, i++
, est dans une branche distincte de l'utilisation de l' i
en face de l'opérateur d'affectation (j'ai marqué chacune de ces évaluations, avec une ★). Donc, nous avons certainement un comportement indéterminé! Je recommande fortement le dessin de ces diagrammes, si vous jamais demandé si votre séquençage des évaluations va vous causer des soucis.
Donc, nous en arrivons maintenant à la question sur le fait que la valeur de i
avant l'opérateur d'affectation n'a pas d'importance, car nous écrire sur elle de toute façon. Mais en fait, dans le cas général, ce n'est pas vrai. Nous pouvons surcharger l'opérateur d'affectation et de faire usage de la valeur de l'objet avant la cession. La norme ne se soucie pas de ce que nous n'utilisons que les règles sont définies telles que la présence d'un calcul de la valeur non avec un effet secondaire va être un comportement indéterminé. Pas de mais. Ce comportement indéfini est là pour permettre au compilateur d'émettre plus d'un code optimisé. Si l'on ajoute le séquençage de l'opérateur d'affectation, cette optimisation ne peut pas être utilisé.