Apakah destruktor objek lokal di dalam loop dijamin akan dipanggil sebelum iterasi berikutnya?

11

Ketika saya memiliki loop dan di dalam loop ini membuat variabel stack baru (tidak mengalokasikannya di heap dan variabel memegangnya dinyatakan di dalam tubuh loop), adalah destruktor objek ini dijamin akan dipanggil sebelum iterasi berikutnya dimulai, atau mungkin loop terbuka oleh kompiler mengubah sesuatu tentang itu?

pengguna1282931
sumber
1
Loop membuka gulungan per se tidak akan mengubah urutan eksekusi. Namun, paralelisasi loop dapat melakukan ini.
Adrian Mole

Jawaban:

8

Dari n4800:

§6.3.3 Lingkup Blok :

Nama yang dinyatakan dalam blok (8.3) adalah lokal untuk blok itu; ini memiliki lingkup blok. Cakupan potensialnya dimulai pada titik deklarasi (6.3.2) dan berakhir pada akhir bloknya. Variabel yang dideklarasikan pada lingkup blok adalah variabel lokal.

§10.3.6 Destructors :

Sebuah destructor dipanggil secara implisit [...] ketika blok di mana sebuah objek dibuat keluar (8.7)

§4.1.1 Mesin abstrak :

Ketentuan ini kadang-kadang disebut aturan "as-if", karena suatu implementasi bebas untuk mengabaikan persyaratan apa pun dari dokumen ini selama hasilnya seolah-olah persyaratan tersebut telah dipatuhi, sejauh dapat ditentukan dari perilaku yang dapat diamati dari programnya .

[Tekankan milikku]

Jadi iya. Variabel Anda keluar dari ruang lingkup pada akhir loop (yang merupakan blok) dan karenanya destruktornya disebut sejauh siapa pun yang mengamati perilaku program dapat mengetahui .

Paul Evans
sumber
1
Tidak ada di sana tentang KAPAN perusak disebut.
mencolok
2
@stark Yang memungkinkan mereka melakukan ini adalah aturan as-if. Standar hanya menentukan perilaku mesin abstrak. Tidak yakin apakah perlu masuk ke semua detail dalam jawaban di sini.
Max Langhof
2
@stark Ini, IMO, tidak relevan dengan pertanyaan. Anda mungkin juga mengatakan bahwa destruktor dapat diuraikan, dan karenanya tidak calldiedit sama sekali. Atau, jika mereka secara efektif (as-jika aturan) tidak melakukan apa-apa, mungkin tidak ada perakitan untuk destruktor yang dihasilkan.
Daniel Langr
2
@stark See Apa sebenarnya aturan "as-if"? .
Daniel Langr
2
@stark Di mana didefinisikan apa ? Perhatikan bahwa diskusi ini tidak sesuai dengan pertanyaan. Anda dapat mengajukan pertanyaan lain yang terpisah tentang masalah ini.
Daniel Langr
8

Iya. Lebih mudah untuk memvisualisasikan ketika Anda mempertimbangkan "blok" di mana Anda mendeklarasikan variabel, yaitu antara sepasang kawat gigi. Loop adalah blok itu sendiri, dan ketika mencapai braket penutup, sebelum iterasi berikutnya, semua destruktor variabel penyimpanan otomatis yang dinyatakan dalam loop disebut.

mungkin loop membuka gulungan oleh kompiler mengubah sesuatu tentang itu?

Sebagai aturan umum, jangan berpikir tentang apa yang akan dioptimalkan oleh kompiler, karena masih perlu menjamin perilaku program Anda, apa pun yang dilakukan untuk mengoptimalkannya. Jika demikian, loop unrolling tidak akan mengubah apa pun ke efek itu jika itu terjadi.

JBL
sumber
2
+1 untuk aturan praktis, ketika menulis kode kita tidak perlu khawatir tentang kompiler internal. Akan menambahkan sesuatu dengan semangat yang sama untuk jawaban saya, tetapi sekarang sudah ada di sana
idclev 463035818
copy-elision dan RVO mengubah perilaku program, bukan?
Jean-Baptiste Yunès
@ Jean-BaptisteYunès Mereka berpotensi, bagaimanapun, standar memungkinkan mereka juga per[class.copy.elision]
ChrisMM
Bukan hanya sepasang kawat gigi . Anda dapat menulis for(...) X x{};dan xobjek akan dibangun + dihancurkan di setiap iterasi. Demo langsung . Bagian Standar yang relevan adalah stmt.iter / 2 .
Daniel Langr
@DanielsaysreinstateMonica Per §9.5.2 [stmt.iter]itu murni ekuivalen (penekanan tambang): "Jika substatemen dalam pernyataan iterasi adalah pernyataan tunggal dan bukan pernyataan gabungan, seolah-olah itu ditulis ulang menjadi pernyataan gabungan yang mengandung pernyataan asli. " Intinya, dengan atau tanpa kawat gigi untuk satu pernyataan berarti hal yang persis sama dan kawat gigi itu implisit. Saya menghilangkannya untuk kejelasan.
JBL
2

Destructor dipanggil untuk setiap iterasi. Jadi dalam beberapa kasus lebih cepat untuk mendeklarasikan variabel di luar loop daripada di loop. Dengan asumsi kasus berikut:

std::string temp;
for(int i = 0; i < 10; ++i){
    temp = arr[i];
    doSomething(temp);
}

Destuktor tidak dipanggil saat menggunakan loop dieksekusi. Itu hanya menimpa temp.

Tetapi jika Anda menggunakan std::string temp = arr[i]konstruktor dan destruktor dipanggil untuk setiap iterasi. Saya pikir ini menambahkan sedikit runtime jika Anda memiliki loop yang dieksekusi sangat sering.

Julian Schnabel
sumber
perhatikan bahwa destruktor dipanggil atau tidak bukan hanya masalah kinerja. Ketika Anda memiliki tipe RAII, Anda secara khusus ingin destructor dipanggil pada setiap iterasi
idclev 463035818
tidak yakin itu benar. Bukankah destruktor konten 'temp' ditahan dari iterasi sebelumnya dipanggil tepat ketika temp dipindahkan dengan nilai baru?
user1282931
Saya juga tidak 100% yakin. Perbaiki jawaban saya jika Anda menemukan sesuatu yang salah. :)
Julian Schnabel
0

Destuktor disebut sebelum iterasi berikutnya

Girspoon
sumber
0

Tentu saja dtor disebut pada akhir iterasi dan loop terbuka seharusnya tidak mengubah perilaku ini, karena optimasi lainnya (optimasi tidak boleh memodifikasi perilaku program), kecuali beberapa jenis RVO dan sejenisnya yang dapat menghilangkan beberapa kreasi objek semantik palsu. .

Jean-Baptiste Yunès
sumber