Apakah baik untuk mendefinisikan variabel di dalam satu loop? [Tutup]

15

Instruktur saya pernah mengatakan kepada saya bahwa saya tidak boleh mendefinisikan variabel di dalam satu lingkaran , tetapi saya sejujurnya masih tidak mengerti mengapa.

Apa kerugiannya?

Bisakah ada yang menjelaskan hal itu kepada saya?

pengguna3260672
sumber
7
Bahasa pemrograman apa yang diajarkan instruktur Anda?
Brian
2
Jika Anda mendefinisikan variabel dengan tipe non-primitif dalam satu lingkaran, program Anda mungkin akan berakhir memanggil konstruktor yang tidak perlu setiap kali melalui loop. Jika Anda hanya perlu mendefinisikannya sekali di luar loop, lakukan itu.
Brandin
17
Ketika Anda memiliki kebingungan tentang apa yang dikatakan instruktur, sumber terbaik adalah bertanya kepada instruktur. Mereka dapat memberi Anda komunikasi bolak-balik yang padat yang tidak dapat disediakan situs T&J.
1
Duplikat lintas-situs: Perbedaan antara mendeklarasikan variabel sebelum atau di loop? (dan tentu saja banyak, banyak duplikat di situs itu untuk pertanyaan mendasar seperti itu (termasuk yang hanya tentang C ++)).
Peter Mortensen
2
Nasihat itu khusus untuk suatu konteks. Sebagai masalah gaya pribadi, saya lebih suka mendeklarasikan variabel saya constkecuali ada alasan untuk tidak melakukannya (kebiasaan dari pemrograman fungsional). Entah saya tidak akan memodifikasinya, dan pengoptimal akan mendeteksi ketika mereka tidak diperlukan, atau saya akan dan saya telah mencegah bug serius. Ketika nilai-nilai perantara konstan tersebut khusus untuk iterasi dari loop, itu berarti mendeklarasikannya di dalam loop. Namun, saat lain Anda perlu mendeklarasikan variabel di luar loop, adalah ketika Anda akan merujuk mereka di luar loop; misalnya, hasil yang Anda simpan.
Davislor

Jawaban:

42

Bukan masalah untuk mendefinisikan variabel dalam satu lingkaran. Sebenarnya, ini praktik yang baik, karena pengidentifikasi harus dibatasi pada ruang lingkup sekecil mungkin.

Yang buruk adalah untuk menetapkan variabel dalam satu loop jika Anda bisa menetapkannya sekali saja sebelum loop berjalan. Bergantung pada seberapa kompleks sisi kanan penugasan ini, ini bisa menjadi agak mahal dan bahkan mungkin mendominasi waktu run dari loop. Jika Anda menulis loop yang menggunakan nilai perhitungan yang sama di semua iterasi, Anda harus menghitungnya di atas loop - yang lebih penting daripada meminimalkan cakupannya.

Untuk memperjelas: selama compute()selalu mengembalikan nilai yang sama, ini

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

lebih pintar dari ini:

while (something) {
    int value = compute();
    doSomething(value);
}
Kilian Foth
sumber
2
Bagaimana Anda mendefinisikan variabel dalam loop dan menetapkannya sebelum loop?
Masked Man
6
@MaskedMan, saya pikir Anda salah paham. Yang dimaksud Kilian adalah jika Anda memiliki variabel yang diberi nilai yang sama selama setiap iterasi loop, misalnya, variabel tanggal yang sama diatur ke 1/1/1900, variabel harus dideklarasikan dan nilai tersebut harus ditetapkan sebelum loop.
ps2goat
2
Saya tidak berpikir ada kompiler yang ditulis dalam dua puluh tahun terakhir (di luar kursus kompilasi sarjana) yang tidak akan tahu Anda menetapkan nilai yang sama pada setiap iterasi dan memindahkan tugas itu keluar dari loop.
TMN
14
@ tmn: Jangan pernah membiarkan kompiler melakukan apa yang bisa Anda lakukan sendiri dengan kejelasan kode yang lebih baik.
Robert Harvey
10
@ TMN, belum tentu. Optimalisasi itu hanya dimungkinkan jika kompiler dapat membuktikan bahwa perhitungannya bebas efek samping.
Paul Draper
16

Tipe kompleks memiliki konstruktor dan destruktor non-sepele.

Itu akan dipanggil pada awal dan akhir dari loop body (seperti yang diinisialisasi dan keluar dari ruang lingkup). Jika inisialisasi mahal seperti itu perlu mengalokasikan sebagian memori maka itu harus dihindari.

Namun untuk tipe sepele itu tidak masalah. Alokasi dan deallokasi itu sendiri hanya menambah dan mengurangi nilai dari stack pointer. (yang akan dioptimalkan)

aneh ratchet
sumber
terima kasih, tepatnya jawaban yang saya cari!
gebbissimo
6

Nah, nasihatnya agak terlalu sederhana (itu pernyataan yang meremehkan).
Mengikuti itu berkisar sepanjang jalan dari ide yang baik atas yang peduli dan ide yang buruk untuk mustahil .

  1. Anda harus mengikutinya setiap kali menggunakan kembali lebih murah daripada menghancurkan yang lama dan membuat yang baru.

    #include <iostream>
    #include <string>
    
    int main() {
        std::string s; // Don't needlessly free the buffer
        while ((std::cin >> s))
            std::cout << s;
    }
  2. Anda harus menghindari itu sebagai masalah gaya ketika itu tidak masalah untuk kinerja.

    #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. Anda benar - benar harus menghindari itu ketika memiliki kinerja yang lebih buruk atau semantik yang salah.

    #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. Anda tidak dapat mengikutinya ketika jenis yang digunakan tidak memungkinkan swapping, atau memindahkan-tugas atau menyalin-tugas.

    #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;
        }
    }
Deduplicator
sumber
2
Bergantung pada definisi Anda tentang "dalam satu lingkaran", 1 dapat diubah menjadi for (std::string s; std::cin >> s;) ...dan masih menjadi "di luar"
Caleth