Po pierwsze, nowoczesny C++ został przełączony z (niedostatecznej) koncepcji starej „punktów sekwencji” do nowa koncepcja "sekwencjonowania" (tj. "sekwencjonowanie przed", "sekwencjonowanie po"). Chociaż i = i++
jest wciąż niezdefiniowany, to teraz jest on idealnie zdefiniowany. Reguły sekwencjonowania wielu operatorów powracających do luminancji zostały przerobione.
Po drugie, twoja wersja jest bezpieczna pod starą specyfikacją, a także pod nową. Modyfikacja i
wewnątrz funkcji jest bezpiecznie "odizolowana" od przypisania do i
na zewnątrz. W klasycznych punktach specyfikacji punkty na początku i na końcu funkcji bezpiecznie oddzieliły modyfikacje (i odczyty) od siebie o i
. Nowe zasady sekwencjonowania zachowują ten sam poziom ochrony.
Przykładem ilustrującym ochrony zapewnianej przez wywołanie funkcji może wyglądać następująco
int inc(int &i) { return i++; }
...
int i = 1;
int r1 = i++ * i++ * i++;
// Undefined behavior because of multiple unsequenced side effects
// applied to the same variable
int r2 = inc(i) * inc(i) + inc(i);
// No UB, but order of evaluation is unspecified. Since the result
// depends on the order of evaluation, it is unspecified
int r3 = inc(i) + inc(i) + inc(i);
// Perfectly defined result. Order of evaluation is still unspecified,
// but the result does not depend on it
co informuje kompilator? – tristan
@tristan zazwyczaj kompilator nic nie mówi o UB. – user2079303
gcc ma opcję "-Wsequence-point" – tristan