Bu mükemmel bir uygulamadır.
Döngüler içinde değişkenler oluşturarak, kapsamlarının döngü içinde sınırlı olmasını sağlarsınız. Döngü dışında referans gösterilemez veya çağrılamaz.
Bu yoldan:
Değişkenin adı biraz "genel" ise ("i" gibi), daha sonra kodunuzda bir yerde aynı ada sahip başka bir değişkenle karıştırılma riski yoktur ( -Wshadow
GCC üzerindeki uyarı talimatı kullanılarak da azaltılabilir )
Derleyici, değişken kapsamının döngü içinde sınırlı olduğunu bilir ve bu nedenle değişken yanlışlıkla başka bir yere başvurulursa uygun bir hata iletisi verir.
Son olarak, değişkenin döngünün dışında kullanılamayacağını bildiğinden, bazı özel optimizasyonlar derleyici tarafından daha verimli bir şekilde gerçekleştirilebilir (en önemlisi kayıt ayırma). Örneğin, sonucu daha sonra tekrar kullanmak üzere saklamanıza gerek yoktur.
Kısacası, bunu yapma hakkınız var.
Ancak değişkenin her döngü arasındaki değerini korumasının gerekmediğini unutmayın . Bu durumda, her seferinde başlatmanız gerekebilir. Ayrıca, tek amacı değerini bir döngüden diğerine tutması gereken değişkenleri bildirmek olan döngüyü kapsayan daha büyük bir blok da oluşturabilirsiniz. Bu genellikle döngü sayacının kendisini içerir.
{
int i, retainValue;
for (i=0; i<N; i++)
{
int tmpValue;
/* tmpValue is uninitialized */
/* retainValue still has its previous value from previous loop */
/* Do some stuff here */
}
/* Here, retainValue is still valid; tmpValue no longer */
}
2. soru için: İşlev çağrıldığında değişken bir kez tahsis edilir. Aslında, bir tahsis perspektifinden bakıldığında, (neredeyse) fonksiyonun başlangıcında değişkeni bildirmekle aynıdır. Tek fark kapsamdır: değişken, döngünün dışında kullanılamaz. Değişkenin tahsis edilmemesi bile mümkündür, sadece bazı boş yuvalar (kapsamı sona eren diğer değişkenlerden) yeniden kullanılır.
Kısıtlı ve daha hassas kapsam ile daha doğru optimizasyonlar gelir. Ancak daha da önemlisi, kodunuzun diğer bölümlerini okurken endişelenmeniz gereken daha az durum (yani değişkenler) ile kodunuzu daha güvenli hale getirir.
Bu, bir if(){...}
bloğun dışında bile geçerlidir . Genellikle, yerine:
int result;
(...)
result = f1();
if (result) then { (...) }
(...)
result = f2();
if (result) then { (...) }
yazmak daha güvenli:
(...)
{
int const result = f1();
if (result) then { (...) }
}
(...)
{
int const result = f2();
if (result) then { (...) }
}
Fark, özellikle böyle küçük bir örnekte küçük görünebilir. Ancak daha büyük bir kod tabanına yardımcı olacaktır: şimdi bir result
değeri bloke f1()
etmek için bir risk yoktur f2()
. Her result
biri kesinlikle kendi kapsamıyla sınırlıdır ve rolünü daha doğru hale getirir. Gözden geçiren bir bakış açısından, çok daha hoş, çünkü endişelenecek ve izleyecek daha az uzun menzilli durum değişkenleri var .
Derleyici bile daha iyi yardımcı olacaktır: gelecekte, bazı hatalı kod değişikliklerinden sonra result
düzgün bir şekilde başlatılmadığını varsayarsak f2()
. İkinci sürüm, derleme zamanında net bir hata mesajı belirterek çalışmayı reddeder (çalışma süresinden çok daha iyi). İlk sürüm hiçbir şey tespit f1()
etmeyecek , sonucu sadece ikinci kez test edilecek ve sonucu için karıştırılacaktır f2()
.
Tamamlayıcı bilgiler
Açık kaynaklı araç CppCheck (C / C ++ kodu için statik bir analiz aracı), değişkenlerin optimum kapsamı hakkında bazı mükemmel ipuçları sağlar.
Tahsis hakkındaki yoruma yanıt olarak: Yukarıdaki kural C için geçerlidir, ancak bazı C ++ sınıfları için olmayabilir.
Standart tipler ve yapılar için, değişkenin boyutu derleme zamanında bilinir. C'de "yapı" diye bir şey yoktur, bu nedenle işlev çağrıldığında değişken için alan sadece yığına (herhangi bir başlatma olmadan) tahsis edilecektir. Bu yüzden değişkeni bir döngü içinde bildirirken "sıfır" maliyet vardır.
Ancak, C ++ sınıfları için, daha az bildiğim bu yapıcı şey var. Derleyici aynı alanı yeniden kullanmak için yeterince akıllı olacağından, tahsis muhtemelen sorun olmayacaktır, ancak başlatma her döngü yinelemesinde gerçekleşecektir.