Pertanyaan ini berasal dari komentar ini: Penjelasan seumur hidup Lambda untuk C ++ 20 coroutine
tentang contoh ini:
auto foo() -> folly::coro::Task<int> {
auto task = []() -> folly::coro::Task<int> {
co_return 1;
}();
return task;
}
Jadi pertanyaannya adalah apakah mengeksekusi coroutine yang dikembalikan oleh foo
akan menghasilkan UB.
"Memanggil" fungsi anggota (setelah masa hidup objek berakhir) adalah UB: http://eel.is/c++draft/basic.life#6.2
... pointer apa pun yang mewakili alamat lokasi penyimpanan di mana objek akan atau terletak dapat digunakan tetapi hanya dengan cara yang terbatas. [...] Program memiliki perilaku yang tidak terdefinisi jika:
[...]
- pointer digunakan untuk mengakses anggota data non-statis atau memanggil fungsi anggota non-statis objek , atau
Namun, dalam contoh ini:
- itu
()
operator lambda disebut sementara seumur hidup lambda masih berlaku - Kemudian ditangguhkan,
- maka lambda dihancurkan,
- dan kemudian fungsi anggota (operator
()
) dilanjutkan di beberapa titik sesudahnya.
Apakah pembukaan kembali ini dianggap sebagai perilaku yang tidak terdefinisi?
sumber
this
pointer tidak valid. Pertimbangkan juga diskusi dalam komentar.Jawaban:
[dcl.fct.def.coroutine] p3 :
Parameter objek implisit dalam contoh Anda adalah referensi const, dan karenanya referensi itu akan menggantung ketika eksekusi dilanjutkan setelah objek penutupan telah dihancurkan.
Namun, pada catatan objek yang dihancurkan selama pelaksanaan fungsi anggota, ini memang baik-baik saja, dan tidak lain dari standar itu sendiri menyiratkan ini dalam [dasar] :
(NB: UB di atas adalah karena implisit
this
tidak dicuci dan masih mengacu pada parameter objek implisit.)Jadi contoh Anda tampaknya terdefinisi dengan baik, tergantung pada gagasan bahwa dimulainya kembali eksekusi tidak jatuh di bawah aturan yang sama dengan doa asli. Perhatikan bahwa referensi ke objek penutup mungkin menjuntai, tetapi tidak diakses dengan cara apa pun antara suspensi dan dimulainya kembali.
sumber