Kiedy mam pętlę i wewnątrz tej pętli tworzę nową zmienną stosu (nieprzydzielając jej na stercie i zmiennej utrzymującej ją zadeklarowaną wewnątrz korpusu pętli), to jest gwarantem, że destruktor tego obiektu zostanie wywołany przed rozpoczęciem kolejnej iteracji, lub może rozwijanie pętli przez kompilator coś zmienić?
c++
destructor
użytkownik1282931
źródło
źródło
Odpowiedzi:
Od
n4800
:§6.3.3 Zakres bloku :
§ 10.3.6 Niszczyciele :
§4.1.1 Maszyna abstrakcyjna :
[Moje podkreślenie]
Więc tak. Twoja zmienna wykracza poza zakres na końcu pętli (która jest blokiem), a zatem jej destruktor jest wywoływany tak daleko, jak każdy, kto obserwuje zachowanie programu .
źródło
call
w ogóle nie być edytowane . Lub, jeśli skutecznie (jak gdyby) nic nie robią, może nie być żadnego zestawu dla takich generatorów.Tak. Łatwiej jest zwizualizować, gdy weźmie się pod uwagę „bloki”, w których deklaruje się zmienną, tj. Między którą parą nawiasów klamrowych. Pętla sama w sobie jest blokiem, a gdy osiągnie nawias zamykający, przed następną iteracją wywoływane są wszystkie destruktory automatycznych zmiennych pamięci zadeklarowanych w pętli.
Zasadniczo nie myśl o tym, co kompilator zoptymalizuje, ponieważ nadal musi gwarantować zachowanie twojego programu, bez względu na to, co robi, aby go zoptymalizować. W takim przypadku rozwinięcie pętli nie zmieni niczego w tym zakresie, jeśli tak się stanie.
źródło
[class.copy.elision]
for(...) X x{};
ax
obiekt będzie konstruowany + niszczony w każdej iteracji. Demo na żywo . Odpowiednią sekcją standardową jest stmt.iter / 2 .[stmt.iter]
jest to czysto równoważne ( wyróżnienie moje): „Jeśli podstacja w instrukcji iteracji jest pojedynczą instrukcją, a nie instrukcją złożoną , to tak, jakby została przepisana na instrukcję złożoną zawierającą oryginalne oświadczenie. ”. Zasadniczo, z nawiasami klamrowymi lub bez dla jednej instrukcji oznacza dokładnie to samo, a nawiasy klamrowe są niejawne. Pominąłem to dla jasności.Destruktor jest wywoływany przy każdej iteracji. Dlatego w niektórych przypadkach szybsze jest zadeklarowanie zmiennej poza pętlą zamiast w pętli. Zakładając następujący przypadek:
Destruktor nie jest wywoływany podczas wykonywania pętli. Po prostu zastępuje
temp
.Ale jeśli użyjesz
std::string temp = arr[i]
konstruktora i wywoływany jest destruktor dla każdej iteracji. Myślę, że to dodaje trochę czasu działania w przypadku, gdy pętla jest wykonywana bardzo często.źródło
Destruktor jest wywoływany przed następną iteracją
źródło
Oczywiście dtor jest wywoływany na końcu iteracji i rozwijanie pętli nie powinno modyfikować tego zachowania, jak każda inna optymalizacja (optymalizacja nie powinna modyfikować zachowania programu), z wyjątkiem pewnego rodzaju RVO i podobnych, które mogą wyeliminować niektóre semantycznie fałszywe tworzenie obiektów .
źródło