Untuk loop di dalam kurung kurawalinya sendiri

117

Saya telah menemukan tata letak for-loop ini:

#include <iostream>
int main()
{
    {
        for (int i = 0; i != 10; ++i)
        {
            std::cout << "delete i->second;" << std::endl;
        }
    }

    {
        for (size_t i = 0; i < 20; ++i)
        {
            std::cout << "delete m_indices[i];" << std::endl;
        }
    }
    return 0;
}

Saya bertanya-tanya untuk apa lapisan kawat gigi ekstra ini? Ini muncul beberapa kali di basis kode kami.

Ed Norman
sumber
47
Mereka benar-benar berlebihan dalam potongan kode yang Anda posting
EdChum
25
kompiler apa yang telah digunakan dengan kode ini? Secara khusus apakah VS 6 digunakan?
UKMonkey
5
@EdNorman sekarang dengan suntingan Anda, itu jauh lebih jelas. Sepertinya jawaban yang benar adalah yang diberikan oleh UKMonkey. Dengan kompiler C ++ modern Anda dapat dengan mudah melepaskan tanda kurung kurawal.
Jabberwocky
8
Atau, itu dapat dihasilkan kode (menghela nafas seseorang yang baru saja memahami Rhapsody)
Mawg mengatakan kembalikan Monica
4
Salah satu alasan yang mungkin adalah jika kode pernah memiliki (atau dimaksudkan untuk dimiliki di masa depan) arahan paralel OpenMP.
jamesqf

Jawaban:

286

Dahulu kala, beberapa bulan yang lalu, VS6 ada dan populer. Namun gagal untuk menyesuaikan dengan sejumlah standar C ++; yang wajar pada saat dirilis sebelum (pada tahun yang sama) standar resmi dirilis; Namun itu mematuhi draft standar sejauh yang saya tahu.

Salah satu standar yang berubah antara draf dan standar resmi, adalah masa pakai variabel loop yang dibuat di bagian pertama; mengarah ke kode berikut gagal dikompilasi

{
    for (int i=0; i<1; ++i){}
    for (int i=0; i<2; ++i){}
}

karena ididefinisikan ulang oleh perulangan for kedua.

Sementara kompiler lain juga mengalami bug ini; Saya menyoroti VS6 karena itu tetap satu-satunya versi studio visual selama beberapa tahun setelah rilis standar, tetapi tidak pernah merilis pembaruan untuk edisi khusus ini; artinya memiliki dampak yang lebih signifikan.

Solusi untuk ini adalah dengan memaksa seluruh loop for ke dalam cakupannya sendiri seperti yang telah Anda tunjukkan.

UKMonkey
sumber
49
Tidak perlu mencari VS6 untuk melihat @bolov itu, setel "Paksa Kesesuaian di Untuk Lingkup Loop" ke "Tidak" di VS2015, dan nikmati ;-)
alain
5
@alain "opsi 'Zc: forScope-' tidak digunakan lagi dan akan dihapus dalam rilis mendatang" dan dikompilasi tanpa masalah ... Saya sedih
bolov
7
GCC sebelum versi 2.7 juga menunjukkan perilaku ini. Lihat docs.freebsd.org/info/g++FAQ/g++FAQ.info.for_scope.html
Jeremy
5
@ Damon bukan saat VS6 pertama kali dirilis; namun ketika standar berubah, pembaruan yang sesuai dengannya tidak pernah dirilis. VS6 tetap populer selama beberapa tahun setelah standar diubah.
UKMonkey
7
Mengaitkan ini dengan dosa kompilator Microsoft lama adalah palsu. Perilaku ini sebenarnya adalah fitur dari draf standar C ++, dan sejumlah kompiler melakukannya (tidak hanya kompiler Microsoft). Dari memori, itu diubah dalam draf selama sekitar 1995 untuk membuat variabel lokal ke loop - sekitar tiga tahun sebelum standar C ++ pertama diratifikasi. Jadi kebanyakan kompiler C ++ sebelum (sekitar) 1996 bekerja dengan cara ini.
Peter
15

{dan }akan membuat ruang lingkup dan jika Anda menentukan beberapa variabel dalam ruang lingkup Anda tidak dapat mengaksesnya dari luar. Tapi forsudah buat ruang lingkup itu. Begitu

{for(int i = 0; i < count; ++i){}} 

sama dengan

for(int i = 0; i < count; ++i){}

tetapi jika Anda mendefinisikan sesuatu di antara keduanya, ada perbedaan

{int a = 0; for(int i = 0; i < count; ++i){}}

Dalam contoh ini, atidak akan dapat diakses dari luar ruang lingkup.

cokceken.dll
sumber
2

Dalam contoh khusus Anda, tidak ada alasan untuk mereka.

Terkadang Anda mungkin ingin membuat ruang lingkup untuk variabel:

float average;
// ...

{
int sum = 0;
for (int i = 0; i < count; ++i)
{
   sum += v[i];
}
average = (float)sum / count;
}

// use average
// sum not in scope here

Namun saya melihat ini sebagai anti-pola. Biasanya jika Anda merasa perlu melakukan ini maka kemungkinan besar itu forharus menjadi fungsinya sendiri.

bolov
sumber
Oke jika Anda berpikir itu harus dalam fungsinya sendiri (saya bisa memikirkan berkali-kali di mana itu hanya akan menambah overhead paling sedikit tetapi saya tidak akan pergi ke sana) pertanyaan hipotetis untuk Anda: bagaimana jika Anda membutuhkan lingkup lokal tertentu untuk kasus sakelar? Tentu ada kalanya menambahkan ruang lingkup tambahan (yang tentu saja berfungsi juga) (perhatikan bahwa untuk contoh Anda, saya sama sekali tidak menganggap fungsi terpisah adalah ide yang buruk) tidak diperlukan tetapi di lain waktu tidak sesederhana itu bahkan jika ada cara lain.
Pryftan
2

Ini adalah lingkup blok yang ditandai dengan {}kawat gigi. Biasanya digunakan untuk menandai area penyimpanan otomatis . Dalam kasus Anda, tampaknya tidak melakukan apa pun karena loop for memiliki cakupannya sendiri dalam C ++ standar.

Ron
sumber