Bir döngü içindeki yerel bir nesnenin yok edicisinin bir sonraki yinelemeden önce çağrılması garanti ediliyor mu?


11

Bir döngü var ve bu döngü içinde yeni bir yığın değişkeni (yığın ve ayırma gövdesi içinde bildirilen değişken tutan ayırma değil) oluşturmak, bir sonraki yineleme başlamadan önce çağrılacak garanti bu nesnenin yıkıcı olduğunu, ya da olabilir derleyici tarafından döngü unrolling bu konuda bir şey değiştirmek?


1
Döngü seçemeden kendi başına yürütme sırasını değiştirmez. Ancak, döngü paralelleştirmesi bunu yapabilir.
Adrian Mole

Yanıtlar:


8

Gönderen n4800:

§6.3.3 Blok Kapsamı :

Bir blokta (8.3) bildirilen bir isim, o blok için yereldir; blok kapsamı vardır. Potansiyel kapsamı beyan noktasında (6.3.2) başlar ve bloğunun sonunda biter. Blok kapsamında bildirilen bir değişken yerel bir değişkendir.

§10.3.6 Yıkıcılar :

Bir nesnenin yaratıldığı blok çıktığında bir yıkıcı dolaylı olarak çağrılır [...]

§4.1.1 Soyut makine :

Bir uygulama uzun gereksinimi itaat olsaydı, hem sonucudur kadar bu belgenin herhangi bir şartı dikkate almayın, çünkü bu hüküm bazen “olarak eğer” kuralını denir kadarıyla gözlenebilen davranışlarından belirlenebilir program .

[Vurgu madeni]

Yani evet. Değişkeniniz döngünün sonunda (bir blok olan) kapsam dışına çıkar ve bu nedenle yıkıcısı, programın davranışını gözlemleyen herkesin anlayabildiği kadarıyla çağrılır .


1
Orada yıkıcı ne zaman çağırılır.
stark

2
@stark Bunu yapmalarına izin veren as-if kuralıdır. Standart yalnızca soyut makinenin davranışını belirtir. Buradaki yanıtlarda tüm bu ayrıntılara girmenin gerekli olup olmadığından emin değilim.
Max Langhof

2
@stark Bu, IMO, soru ile ilgisiz. Yıkıcıların sıralı olabileceğini ve bu nedenle hiç basılmayabileceğini de söyleyebilirsiniz call. Veya etkili bir şekilde (eğer kural olarak) hiçbir şey yapmazlarsa, bu tür yıkıcılar için bir montaj olmayabilir.
Daniel Langr


2
@stark Nerede ne tanımlanır ? Bu tartışmanın sorunun konusu olmadığını unutmayın. Bu sorun hakkında başka bir soru sorabilirsiniz.
Daniel Langr

8

Evet. Bir değişkeni bildirdiğiniz "blokları" düşündüğünüzde, yani hangi parantez çifti arasında görselleştirmek daha kolaydır. Döngü kendi içinde bir bloktur ve kapanma dirseğine ulaştığında, bir sonraki yinelemeden önce, döngüde bildirilen otomatik depolama değişkenlerinin tüm yıkıcıları çağrılır.

derleyici tarafından döngü açma bu konuda bir şey değiştirebilir?

Genel bir kural olarak, derleyicinin neyi optimize edeceğini düşünmeyin, çünkü onu optimize etmek için ne yaparsa yapsın, programınızın davranışını hala garanti etmesi gerekir. Bu durumda, döngü çözme gerçekleşirse bu etki için hiçbir şey değiştirmez.


2
Başparmak kuralı için +1, kod yazarken derleyici içleri hakkında endişelenmemelisiniz.
Cevabımla

copy-elision ve RVO program davranışını değiştirir, değil mi?
Jean-Baptiste Yunès

@ Jean-BaptisteYunès Ancak, potansiyel olarak onlara izin verir[class.copy.elision]
ChrisMM

Sadece parantez çifti değil . Yazabilirsiniz for(...) X x{};ve xnesne her yinelemede inşa edilecek + tahrip edilecektir. Canlı demo . İlgili bir Standart bölüm stmt.iter / 2'dir .
Daniel Langr

@DanielsaysreinstateMonica §9.5.2 uyarınca [stmt.iter]tamamen eşdeğerdir (benimki vurgu): "Bir yineleme ifadesindeki alt ifade, bir bileşik ifadesi değil, tek bir ifadeyse , bir bileşik ifadesi olarak yeniden yazılmış gibi orijinal beyanı. ". Özünde, tek bir ifade için parantez olsun veya olmasın, tam olarak aynı şey anlamına gelir ve parantezler örtüktür. Anlaşılır olması için atladım.
JBL

2

Yıkıcı her yineleme için çağrılır. Bu nedenle, bazı durumlarda , döngü yerine döngü dışında bir değişken bildirmek daha hızlıdır . Aşağıdaki durumu varsayarsak:

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

Döngü kullanılırken yıkıcı çağrılmaz. Sadece geçersiz kılar temp.

Ancak std::string temp = arr[i]yapıcı ve yıkıcı kullanırsanız her yineleme için yıkıcı çağrılır. Çok sık yürütülen bir döngü olması durumunda bu biraz çalışma zamanı eklediğini düşünüyorum.


yıkıcıların çağrılıp çağrılmalarının sadece bir performans meselesi olmadığını unutmayın. Bir RAII türünüz olduğunda, özellikle her yinelemede
yıkıcının çağrılmasını istersiniz

bunun doğru olduğundan emin değilim. 'Yeni' içeriğinin yıkıcısı, temp yeni değerle yeniden atandığında önceki yinelemeden tutuyor doğru çağrılmıyor mu?
user1282931

Ben de% 100 emin değilim. Yanlış bir şey bulduysanız cevabımı düzeltin. :)
Julian Schnabel


0

Tabii ki dtor yinelemenin sonunda çağrılır ve bazı anlamsal olarak sahte nesne yaratımlarını ortadan kaldırabilecek bir tür RVO ve benzerleri hariç, diğer optimizasyonlar (bir optimizasyon program davranışını değiştirmemelidir) gibi döngü çözme bu davranışı değiştirmemelidir. .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.