สำหรับห่วงภายในวงเล็บปีกกาของตัวเอง


117

ฉันเจอเลย์เอาต์ for-loop นี้:

#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;
}

ฉันสงสัยว่าการจัดฟันชั้นพิเศษนี้มีไว้เพื่ออะไร? สิ่งนี้ปรากฏขึ้นสองสามครั้งในฐานรหัสของเรา


47
ข้อมูลเหล่านี้ไม่จำเป็นอย่างยิ่งในข้อมูลโค้ดที่คุณโพสต์
EdChum

25
มีการใช้คอมไพเลอร์อะไรกับโค้ดนี้บ้าง? VS 6 ถูกนำมาใช้โดยเฉพาะหรือไม่?
UKMonkey

5
@EdNorman ตอนนี้การแก้ไขของคุณชัดเจนขึ้นมาก ดูเหมือนว่าคำตอบที่ถูกต้องคือคำตอบที่ UKMonkey ให้ไว้ ด้วยคอมไพเลอร์ C ++ ที่ทันสมัยคุณสามารถวางวงเล็บปีกกาได้อย่างง่ายดาย
Jabberwocky

8
หรืออาจสร้างรหัส (ถอนใจคนที่เพิ่งมาจับ Rhapsody)
Mawg กล่าวคืนสถานะ Monica

4
เหตุผลหนึ่งที่เป็นไปได้คือถ้ารหัสเคยมี (หรือตั้งใจจะมีในอนาคต) คำสั่งแบบขนาน OpenMP
jamesqf

คำตอบ:


286

กาลครั้งหนึ่งมีหลายดวงที่ผ่านมาVS6มีอยู่จริงและเป็นที่นิยม อย่างไรก็ตามมันล้มเหลวในการปฏิบัติตามมาตรฐาน C ++ จำนวนมาก ซึ่งสมเหตุสมผลในเวลาที่เปิดตัวก่อนหน้านี้ (ในปีเดียวกัน) มาตรฐานได้รับการเผยแพร่อย่างเป็นทางการ อย่างไรก็ตามมันเป็นไปตามร่างของมาตรฐานเท่าที่ฉันทราบ

หนึ่งในมาตรฐานที่เปลี่ยนแปลงระหว่างแบบร่างและมาตรฐานอย่างเป็นทางการคืออายุการใช้งานของตัวแปรลูปที่สร้างขึ้นในส่วนแรก นำไปสู่การคอมไพล์โค้ดต่อไปนี้ไม่สำเร็จ

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

เพราะiถูกกำหนดใหม่โดยวินาทีสำหรับลูป

ในขณะที่คอมไพเลอร์อื่น ๆ ก็ประสบปัญหานี้เช่นกัน ฉันเน้น VS6 one เนื่องจากยังคงเป็นเวอร์ชันเดียวของสตูดิโอภาพเป็นเวลาหลายปีหลังจากการเปิดตัวมาตรฐาน แต่ไม่เคยออกการอัปเดตสำหรับปัญหานี้โดยเฉพาะ หมายความว่ามันมีผลกระทบที่สำคัญกว่า

วิธีแก้ปัญหานี้คือบังคับให้ทั้งวงวนอยู่ในขอบเขตของมันเองตามที่คุณได้แสดงไว้


49
ไม่ต้องหา VS6 เพื่อดูว่า @bolov ตั้งค่า "Force Conformance in For Loop Scope" เป็น "No" ใน VS2015 แล้วก็สนุกได้เลย ;-)
เลน

5
@alain "option" Zc: forScope- "เลิกใช้งานแล้วและจะถูกลบออกในอนาคต" และรวบรวมได้โดยไม่มีปัญหา ... ฉันเสียใจ
bolov

7
GCC ก่อนเวอร์ชัน 2.7 ก็แสดงพฤติกรรมนี้เช่นกัน ดูdocs.freebsd.org/info/g++FAQ/g++FAQ.info.for_scope.html
Jeremy

5
@Damon ไม่ใช่ตอนที่ VS6 เปิดตัวครั้งแรก อย่างไรก็ตามเมื่อมาตรฐานเปลี่ยนไปการอัปเดตที่สอดคล้องกับมาตรฐานเหล่านี้จะไม่ถูกเผยแพร่ VS6 ยังคงได้รับความนิยมเป็นเวลาสองสามปีหลังจากเปลี่ยนมาตรฐาน
UKMonkey

7
การระบุว่าสิ่งนี้เป็นบาปของคอมไพเลอร์ Microsoft รุ่นเก่าถือเป็นของปลอม พฤติกรรมนี้เป็นคุณลักษณะของมาตรฐาน C ++ ฉบับร่างและคอมไพเลอร์จำนวนหนึ่งทำสิ่งนี้ (ไม่ใช่เฉพาะคอมไพเลอร์ของ Microsoft) จากหน่วยความจำมีการเปลี่ยนแปลงในแบบร่างในช่วงประมาณปี 1995 เพื่อให้ตัวแปรอยู่ในระบบเป็นลูป - ประมาณสามปีก่อนที่มาตรฐาน C ++ แรกจะได้รับการให้สัตยาบัน ดังนั้นคอมไพเลอร์ C ++ ส่วนใหญ่ที่เกิดขึ้นก่อน (ประมาณ) ปี 1996 จึงทำงานในลักษณะนี้
ปีเตอร์

15

{และ}จะสร้างขอบเขตและหากคุณกำหนดตัวแปรบางตัวในขอบเขตคุณจะไม่สามารถเข้าถึงได้จากภายนอก แต่forสร้างขอบเขตนั้นแล้ว. ดังนั้น

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

เหมือนกับ

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

แต่ถ้าคุณกำหนดบางสิ่งระหว่างพวกเขามีความแตกต่าง

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

ในตัวอย่างนี้aจะไม่สามารถเข้าถึงได้จากภายนอกขอบเขต


2

ในตัวอย่างเฉพาะของคุณไม่มีเหตุผลสำหรับพวกเขา

บางครั้งคุณอาจต้องการสร้างขอบเขตสำหรับตัวแปร:

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

อย่างไรก็ตามฉันเห็นว่านี่เป็นการต่อต้านรูปแบบ โดยปกติแล้วหากคุณพบว่าตัวเองต้องการที่จะทำสิ่งนี้ก็น่าforจะเป็นหน้าที่ของตัวเอง


โอเคถ้าคุณคิดว่ามันควรจะอยู่ในหน้าที่ของมันเอง (ฉันคิดได้หลายครั้งที่จะเพิ่มค่าใช้จ่ายอย่างน้อยที่สุด แต่ฉันจะไม่ไปที่นั่น) คำถามสมมุติสำหรับคุณ: แล้วถ้าคุณต้องการ a ขอบเขตเฉพาะในกรณีสวิตช์? มีหลายครั้งที่การเพิ่มขอบเขตเพิ่มเติม (ซึ่งแน่นอนว่าฟังก์ชันก็ทำได้เช่นกัน) (โปรดทราบว่าสำหรับตัวอย่างของคุณฉันไม่คิดว่าฟังก์ชันแยกต่างหากเป็นความคิดที่ไม่ดี) เป็นสิ่งที่ไม่จำเป็น แต่ในบางครั้งก็ไม่ง่ายอย่างนั้นแม้ว่า มีวิธีอื่น ๆ
Pryftan

2

เป็นขอบเขตบล็อกที่มีเครื่องหมาย{}วงเล็บปีกกา มันมักจะถูกนำมาใช้ในการทำเครื่องหมายในพื้นที่ของการจัดเก็บข้อมูลโดยอัตโนมัติ ในกรณีของคุณดูเหมือนว่าจะไม่ทำอะไรเลยเนื่องจากfor loopมีขอบเขตของตัวเองใน C ++ มาตรฐาน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.