2013-01-22 23 views
15

Aşağıdaki işlev verildiğinde, yerel değişkenlerin her biri yığında bildirilir mi? Bu durumda Koşullu Yığın Değişkenleri

std::string reallyCoolFunction(unsigned int a) 
{ 
    if(a < 20) 
    { 
    std::string result1 = "This function is really cool"; 
    return result1; 
    } 

    if(a >=20 && a <= 40) 
    { 
    std::string result2 = "This function is kind of cool"; 
    return result2; 
    } 

    if(a > 40) 
    { 
    std::string result3 = "This function is moderately cool"; 
    return result3; 
    } 

std::string result4 = "This function really isn't that cool"; 
return result4; // remove warning 

} 

, tek std::string aslında gereklidir, tüm 4 stack üzerinde alırım, yoksa sadece 1 ayrılan alır?

cevap

14

karar derleyici kalmıştır: otomatik değişkenler kapsam dışına çıkar çünkü sonraki kapsamında gelmeden önce kendi hafızasını yeniden kullanabilir derleyici . "Yığın" değişkenlerinin aslında C++ şartnamesine göre otomatik depolama süresine sahip değişkenleri olduğunu ve bu nedenle yığınta bulunmayabileceklerini unutmayın.

+0

Cevabımda bahsetmeyi unuttuğum önemli bir parça var - gerçeği çoğunun Dize yığında ayrılmaz. Ben –

+0

@IvayloStrandjev bahsetmeye değer olduğunu düşünüyorum Kesinlikle - Ben bu nedenle çok neden :) – dasblinkenlight

+0

otomatik depolama garanti yığın davranış garanti etti. "yığın" ifadesi budur. "aslında" aslında oldukça acımasız bir kelimedir. otomatik bir değişken, yalnızca eğer kuralın altında en iyi duruma getirilerek yığına yerleştirilmekten kaçınılabilir ve sonra * bu, yığının üzerine tahsis edildiğinden, bu nedenle bu konuda büyük bir not oluşturmak için çok anlamlı değildir. –

10

Çoğu derleyicide yalnızca bir dize tahsis edilir. std::string'un dinamik bellek kullanmasına rağmen, içeriğinin çoğunun yine de öbekte ayrılacağını unutmayın.

+5

Dize * dinamik bellek kullanabilir * ancak zorunlu olmayabilir. Örneğin, MSVC'nin standart kitaplığındaki küçük dizgi optimizasyonuna bakın. –

+0

@ArneMertz oh wow Bunu bilmiyordum. Teşekkür ederim :) –

2

Derleyiciye bağlı olarak değişir.
Derleyici, yalnızca bir dizenin gerekip gerekmediğini belirleyecek kadar akıllısa, yalnızca bir dizge için kod yayar.

Derleyiciniz yeterince akıllı mı?

kolay yolu oluşturulan montaj kodu kontrol etmektir.

Tüm 4 yığın ayrılacağını mı, yoksa yalnızca 1 ayrılacağını geliyor?

o, dize nesne işlevi ancak dize için belleğe yerel yığın üzerinde bulunan 1 veya 4 dizeleri freestore tahsis edilir olun.

+0

* 1 veya 4 dizgiler olun, string nesnesi işlev için yerel yığın üzerinde bulunur, ancak dize için bellek freestore içinde ayrılır. * => SSO: Kısa Dize Optimizasyonu (Dirkumware ve libC++ uygulanan) –

+0

@MatthieuM .: Doğru ve katılıyorum. Düzeltme için teşekkür ederim. Daha kesin olmak gerekirse, bu bir uygulama detayıdır. Standart, * depolamanın yapılmasının zorunlu olduğu yerlerde * sadece, std :: string'in uygulanması gereken bazı gözlemlenebilir davranışları zorunlu kılmaktadır. –

+1

Evet, C++ 03 ve C++ 11 arasında kayda değer bir değişiklik olsa da, gcc'nin optimizasyonu (Copy On Write) artık yeni kısıtlamalar nedeniyle mümkün değildir. –

0

Bu durumda derleyicinin 4, 1, 2 veya 3 değişken oluşturmasına izin verilir. Ama farkında olduğum çoğu derleyici, sonuç4 işleyişin tüm kapsamı içinde olduğundan sadece bir veya iki tane yaratacaktır.

Elbette, eğer "doğru" şeyleri yaparsanız, derleyici kafa karıştırıcı olabilir ve kesinlikle gerekenden daha fazlasını yapabilir, bu nedenle kritik işlevselliğe dayanmak özellikle iyi bir şey olmaz.

Düzenleme: std :: string'in yapıcısını yalnızca nesne aslında "kullanılmış" ise çalıştırılması gerektiğini eklemeliyim, böylece kullanılan yığın alanını alabilirsiniz, ancak yapıcıyı çağırmamalıdır. Eğer böyle bir şey yapmak bu önemlidir: Lock için kurucu "çok erken" idam ve [ve simetrik olmalıdır] Aynı kapsamda tahrip edildiği takdirde, Şimdi

void func() 
{ 
    if (something) 
    { 
     Lock myLock(&global_lock_object); // Constructor locks global_lock_object 
     ... do stuff that needs global_lock_object locked ... 
     // end of scope runs destructor of Lock that unlocks global_lock_object. 
    } 
    ... more code that takes a long time to execute but doesn't need lock. ... 
} 

, kilit yapılacağı fonksiyonun tüm süresi boyunca, yanlış olan.

0

Kısa cevap: assembler'a bakın.

Uzun yanıt: Derleyici , 4 ya da yalnızca bazı değişkenlere ihtiyacı olup olmadığını belirlemek için statik denetimler uygulayabilir. Bazı derleyiciler, hata ayıklama modunda 4 farklı değişken ayırabilir, bazıları olmayabilir.Serbest bırakma modunda, bazı optimize ediciler ilk 3'ün her birinin kendi kapsamı içinde olduğunu görebilir ve böylece aynı yere yerleştirilebilir. Bu derleyiciler yığınta iki dize değişkenleri için yer ayırtabilirler. Hiçbir durumda dördüncü değişkenin ilk üç ile bir arada olmadığını görmek için biraz daha fazla analiz gerekir, bu nedenle bazı optimize ediciler kalan iki değişkeni aynı yere koyabilirler.

Amasenin derleyici bunu yapar mı, ve o hala çıkışını analiz eğer adil biraz daha karışık durumda, sadece kesin belirlenebilir bunu yapmaz mı.

6

Büyük olasılıkla ya da (Release olarak) belki ve (Debug) kesinlikle .

Bu, RVO: Dönüş Değeri Optimizasyonu olarak adlandırılır.

Derleyicinin kopyasını tamamen elimine etmesi ve std::string numarasını, arayan tarafından sağlanan yuvasında yuvasına yerleştirmesine izin verilir. Bu ABI'ye özgüdür ve tüm optimizasyonlar sadece bir takım kriterler yerine getirildiğinde geçerlidir; Sizin durumunuzda geçerli olması muhtemeldir.

Denetlemek isterseniz, derleyicinin çıktısını çeviri/en iyileştirme hattının çeşitli aşamalarında kullanmayı deneyebilirsiniz; Takım zincirinize bağlı olarak zor olabilir.

+0

Kazanmak için "sanki" kuralı. – dmckee