Sebelum Anda mulai berteriak perilaku tidak terdefinisi, ini secara eksplisit terdaftar di N4659 (C ++ 17)
i = i++ + 1; // the value of i is incremented
Namun dalam N3337 (C ++ 11)
i = i++ + 1; // the behavior is undefined
Apa yang berubah?
Dari apa yang bisa saya kumpulkan, dari [N4659 basic.exec]
Kecuali jika disebutkan, evaluasi operan dari operator individual dan subekspresi dari ekspresi individu tidak dilakukan. [...] Perhitungan nilai operan operator diurutkan sebelum perhitungan nilai hasil operator. Jika efek samping pada lokasi memori tidak dilakukan relatif terhadap efek samping lain pada lokasi memori yang sama atau perhitungan nilai menggunakan nilai objek apa pun di lokasi memori yang sama, dan mereka tidak berpotensi bersamaan, perilaku tersebut tidak terdefinisi.
Di mana nilai didefinisikan pada [N4659 basic.type]
Untuk tipe yang dapat disalin sepele, representasi nilai adalah sekumpulan bit dalam representasi objek yang menentukan nilai , yang merupakan salah satu elemen diskrit dari serangkaian nilai yang ditentukan implementasi
Dari [N3337 basic.exec]
Kecuali jika disebutkan, evaluasi operan dari operator individual dan subekspresi dari ekspresi individu tidak dilakukan. [...] Perhitungan nilai operan operator diurutkan sebelum perhitungan nilai hasil operator. Jika efek samping pada objek skalar tidak diikutsertakan relatif terhadap efek samping lain pada objek skalar yang sama atau perhitungan nilai menggunakan nilai objek skalar yang sama, perilaku tidak terdefinisi.
Demikian juga, nilai didefinisikan pada [N3337 basic.type]
Untuk tipe yang dapat disalin sepele, representasi nilai adalah sekumpulan bit dalam representasi objek yang menentukan nilai , yang merupakan salah satu elemen diskrit dari serangkaian nilai yang ditentukan implementasi.
Mereka identik kecuali menyebutkan konkurensi yang tidak masalah, dan dengan penggunaan lokasi memori bukannya objek skalar , di mana
Tipe aritmatika, tipe enumerasi, tipe pointer, pointer ke tipe anggota,
std::nullptr_t
,, dan versi yang memenuhi syarat cv dari tipe-tipe ini secara kolektif disebut tipe skalar.
Yang tidak mempengaruhi contoh.
Dari [N4659 expr.ass]
Operator penugasan (=) dan operator penugasan majemuk semuanya grup kanan-ke-kiri. Semua membutuhkan nilai yang dapat dimodifikasi sebagai operan kiri mereka dan mengembalikan nilai yang mengacu pada operan kiri. Hasilnya dalam semua kasus adalah bidang-bit jika operan kiri adalah bidang-sedikit. Dalam semua kasus, penugasan diurutkan setelah perhitungan nilai operan kanan dan kiri, dan sebelum perhitungan nilai ekspresi penugasan. Operan kanan diurutkan sebelum operan kiri.
Dari [N3337 expr.ass]
Operator penugasan (=) dan operator penugasan majemuk semuanya grup kanan-ke-kiri. Semua membutuhkan nilai yang dapat dimodifikasi sebagai operan kiri mereka dan mengembalikan nilai yang mengacu pada operan kiri. Hasilnya dalam semua kasus adalah bidang-bit jika operan kiri adalah bidang-sedikit. Dalam semua kasus, penugasan diurutkan setelah perhitungan nilai operan kanan dan kiri, dan sebelum perhitungan nilai ekspresi penugasan.
Satu-satunya perbedaan adalah kalimat terakhir yang tidak ada di N3337.
Namun kalimat terakhir, seharusnya tidak memiliki kepentingan karena operan kiri i
bukanlah "efek samping lain" atau "menggunakan nilai objek skalar yang sama" karena ekspresi id adalah lvalue.
i = i++ + 1;
.