Döngü içinde bir değişken tanımlamak iyi midir? [kapalı]


15

Eğitmenim bir keresinde bana bir döngü içinde bir değişken tanımlamamam gerektiğini söyledi , ama dürüstçe hala nedenini anlamıyorum.

Bunun dezavantajları nelerdir?

Bunu herhangi bir beden açıklayabilir mi?


7
Eğitmeniniz hangi programlama dilini öğretiyordu?
Brian

2
Bir döngüde ilkel olmayan türde bir değişken tanımlarsanız, programınız döngü boyunca her seferinde yapıcısını gereksiz yere çağırır. Döngünün dışında bir kez tanımlamanız gerekiyorsa, bunu yapın.
Brandin

17
Bir eğitmenin söyledikleri hakkında böyle bir karışıklığa sahip olduğunuzda, en iyi kaynak eğitmene sormaktır. Size bir Soru-Cevap sitesinin sağlayamadığı yoğun ileri ve geri iletişimi sağlayabilirler.

1
Siteler arası yineleme: Döngü öncesi veya döngü içinde değişken bildirme arasındaki fark nedir? (ve elbette böyle bir temel soru için o sitedeki birçok kopya, sadece C ++ ile ilgili olanlar dahil).
Peter Mortensen

2
Bu tavsiye bir bağlama özgüdür. Kişisel bir tarz olarak, constbir neden olmadıkça değişkenlerimi beyan etmeyi tercih ederim (fonksiyonel programlamadan bir alışkanlık). Ya onları değiştirmeyeceğim ve optimizer ne zaman gerekli olmadıklarını tespit etmeli ya da yapacağım ve ciddi bir hatayı önledim. Bu sabit ara değerler, döngünün yinelemesine spesifik olduğunda, bu döngü içinde bunların bildirilmesi anlamına gelir. Değişkenleri döngü dışında bildirmeniz gereken başka bir zaman, döngü dışında bunlara atıfta bulunacağınız zamandır; örneğin, sakladığınız sonuçlar.
Davislor

Yanıtlar:


42

Döngü içindeki bir değişkeni tanımlamak sorun değil . Aslında, iyi bir uygulamadır, çünkü tanımlayıcılar mümkün olan en küçük kapsamla sınırlandırılmalıdır.

Ne kötü etmektir atamak sadece de bir kez atamak eğer bir döngü içinde bir değişken önce döngü çalışır. Ödevin sağ tarafının ne kadar karmaşık olduğuna bağlı olarak, bu oldukça pahalı hale gelebilir ve hatta döngünün çalışma süresine hakim olabilir. Tüm tekrarlamalar aynı hesaplanan değeri kullanan bir döngü yazarsanız, kesinlikle hesaplayabilir gerektiğini yukarıda kapsamını minimize daha önemli olduğunu - döngü.

Açıklığa kavuşturmak için: compute()her zaman aynı değeri döndürdüğü sürece ,

int value = compute();
while (something) {
    doSomething(value);
}

bundan daha akıllı:

while (something) {
    int value = compute();
    doSomething(value);
}

2
Döngüde bir değişkeni nasıl tanımlayıp döngüden önce atayabilirsiniz?
Maskeli Adam

6
@MaskedMan, sanırım yanlış anlıyorsun. Kilian'ın anlamı, bir döngünün her yinelemesi sırasında aynı değere atanan bir değişkeniniz varsa, örneğin aynı tarih değişkeni olarak ayarlanmışsa 1/1/1900, değişken bildirilmeli ve değer döngüden önce atanmalıdır.
ps2goat

2
Son yirmi yılda yazılmış bir derleyici olduğunu sanmıyorum (bir lisans derleyici kursu dışında), her bir yinelemede aynı değeri atadığınızı ve bu atamayı döngüden çıkardığınızı anlayamayacak.
TMN

14
@tmn: Bir derleyicinin önemsiz bir şekilde daha fazla kod netliği ile yapabildiklerinizi yapmasına asla izin vermeyin.
Robert Harvey

10
@TMN, mutlaka değil. Bu optimizasyon ancak derleyici hesaplamanın yan etkisiz olduğunu kanıtlayabilmesi durumunda mümkündür.
Paul Draper

16

Karmaşık tipler önemsiz olmayan yapıcılara ve yıkıcılara sahiptir.

Bunlar döngü gövdesinin başlangıcında ve sonunda çağrılır (başlatıldığında ve kapsam dışına çıktığında). Başlatma, biraz bellek ayırması gerektiği gibi pahalıysa, bundan kaçınılmalıdır.

Ancak önemsiz türler için sorun değil. Tahsis ve dağıtmanın kendisi sadece yığın işaretçisinden bir değer ekler ve çıkarır. (optimize edilecek)


teşekkürler, tam olarak aradığım cevap!
gebbissimo

6

Onun tavsiyesi biraz fazla basit (bu bir eksiklik).
O tüm yol kadar uzanmaktadır ardından iyi bir fikir üzerinde kimin umurunda ve kötü bir fikir için imkansız .

  1. Yeniden kullanım eskisini yok etmek ve yeni bir tane oluşturmaktan daha ucuz olduğunda takip etmelisiniz.

    #include <iostream>
    #include <string>
    
    int main() {
        std::string s; // Don't needlessly free the buffer
        while ((std::cin >> s))
            std::cout << s;
    }
  2. Performans açısından önemli olmadığında bir stil meselesi olarak kaçınmalısınız.

    #include <stdio.h>
    #include <stdlib.h>
    int f(int, int);
    
    int main() {
        for (int i = 0; i < 100; ++i) {
            int x = rand(); // Declared here so you don't need to hunt it down.
            printf("%d => %d\n", x, f(x-1, x+i));
        }
    }
  3. Daha kötü performansa veya yanlış semantiğe sahip olduğunda gerçekten kaçınmalısınız.

    #include <iostream>
    #include <string>
    std::string generate(int);
    
    int main() {
        for(int i = 0; i < 100; ++i) {
            std::string s = generate(i); // Using copy-ellision here
            std::cout << s;
        }
    }
  4. Sen olamaz kullanılan türü ne takas izin verdiğinde onu takip ne de hareket atama ne de kopya atama.

    #include <iostream>
    #include <puzzle>
    
    int main() {
        for (int i = 0; i < 100; ++i) {
            Puzzle x(i); // Puzzle is an immutable class. For whatever reasons.
            std::cout << x;
        }
    }

2
"Bir döngüde" tanımınıza bağlı olarak, 1 değiştirilebilir for (std::string s; std::cin >> s;) ...ve yine "dışarıda" olabilir
Caleth
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.