Vòng lặp for bên trong dấu ngoặc nhọn của chính nó


117

Tôi đã xem qua bố cục for-loop này:

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

Tôi đang băn khoăn không biết niềng răng thêm lớp này để làm gì? Điều này xuất hiện một vài lần trong cơ sở mã của chúng tôi.


47
Chúng hoàn toàn thừa trong đoạn mã bạn đã đăng
EdChum

25
trình biên dịch nào đã được sử dụng với mã này? Cụ thể VS 6 đã được sử dụng chưa?
UKMonkey

5
@EdNorman bây giờ với chỉnh sửa của bạn, nó rõ ràng hơn nhiều. Có vẻ như câu trả lời chính xác là câu trả lời được cung cấp bởi UKMonkey. Với trình biên dịch C ++ hiện đại, bạn có thể đơn giản bỏ dấu ngoặc nhọn.
Jabberwocky

8
Đang Ngoài ra, nó có thể được tạo ra (thở dài ai đó chỉ đến để hiểu thấu với Rhapsody)
Mawg nói Khôi phục Monica

4
Một lý do có thể là nếu mã đã từng có (hoặc dự định có trong tương lai) các lệnh song song OpenMP.
jamesqf 23/03/18

Câu trả lời:


286

Ngày xưa, nhiều trăng trước, VS6 đã tồn tại và phổ biến. Tuy nhiên, nó không thể tuân theo một số tiêu chuẩn C ++; hợp lý vào thời điểm nó được phát hành ngay trước (cùng năm) tiêu chuẩn chính thức được phát hành; Tuy nhiên, nó đã tuân thủ dự thảo của tiêu chuẩn theo như tôi biết.

Một trong những tiêu chuẩn đã thay đổi giữa bản nháp và tiêu chuẩn chính thức, là thời gian tồn tại của các biến vòng lặp for được tạo trong phần đầu tiên; dẫn đến mã sau không biên dịch được

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

iđã được định nghĩa lại bởi vòng lặp for thứ hai.

Trong khi các trình biên dịch khác cũng bị lỗi này; Tôi đánh dấu VS6 vì nó vẫn là phiên bản duy nhất của visual studio trong một số năm sau khi phát hành tiêu chuẩn, nhưng chưa bao giờ phát hành bản cập nhật cho vấn đề cụ thể này; nghĩa là nó có tác động đáng kể hơn.

Một giải pháp cho điều này là buộc toàn bộ vòng lặp for vào phạm vi riêng của nó như bạn đã trình bày.


49
Không cần phải tìm VS6 để xem @bolov đó, hãy đặt "Bắt buộc tuân thủ trong phạm vi vòng lặp" thành "Không" trong VS2015 và tận hưởng ;-)
alain

5
@alain "option 'Zc: forScope-' đã không được dùng nữa và sẽ bị xóa trong bản phát hành trong tương lai" và biên dịch mà không có vấn đề gì ... Tôi rất buồn
bolov 23/03/18

7
GCC trước phiên bản 2.7 cũng thể hiện hành vi này. Xem docs.freebsd.org/info/g++FAQ/g++FAQ.info.for_scope.html
Jeremy

5
@Damon, đó không phải là khi VS6 được phát hành lần đầu tiên; tuy nhiên khi các tiêu chuẩn thay đổi, bản cập nhật phù hợp với chúng không bao giờ được phát hành. VS6 vẫn phổ biến trong một vài năm sau khi các tiêu chuẩn được thay đổi.
UKMonkey

7
Việc gán điều này vào tội lỗi của trình biên dịch Microsoft cũ là không có thật. Hành vi này thực sự là một tính năng của các tiêu chuẩn C ++ dự thảo và một số trình biên dịch đã làm điều này (không chỉ trình biên dịch của Microsoft). Từ bộ nhớ, nó đã được thay đổi trong một bản nháp trong khoảng năm 1995 để biến biến cục bộ thành vòng lặp - khoảng ba năm trước khi tiêu chuẩn C ++ đầu tiên được phê chuẩn. Vì vậy, hầu hết các trình biên dịch C ++ trước (khoảng) 1996 đều hoạt động theo cách này.
Peter

15

{}sẽ tạo một phạm vi và nếu bạn xác định một số biến trong phạm vi, bạn không thể truy cập chúng từ bên ngoài. Nhưng forđã tạo phạm vi đó. Vì thế

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

giống như

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

nhưng nếu bạn xác định điều gì đó giữa chúng, sẽ có sự khác biệt

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

Trong ví dụ này, asẽ không thể truy cập được từ phạm vi bên ngoài.


2

Trong ví dụ cụ thể của bạn, không có lý do gì cho chúng.

Đôi khi bạn có thể muốn tạo phạm vi cho một biến:

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

Tuy nhiên tôi thấy đây là một khuôn mẫu chống đối. Thông thường, nếu bạn thấy mình cần phải làm điều này thì rất có thể forđó là chức năng riêng của nó.


Được rồi nếu bạn nghĩ rằng nó phải có chức năng riêng của nó (tôi có thể nghĩ nhiều lần nơi điều đó sẽ chỉ thêm chi phí ít nhất nhưng tôi sẽ không đi đến đó) một câu hỏi giả định dành cho bạn: nếu bạn cần một phạm vi địa phương cụ thể cho một trường hợp chuyển đổi? Chắc chắn đôi khi việc thêm một phạm vi bổ sung (tất nhiên là một hàm cũng vậy) (lưu ý rằng đối với ví dụ của bạn, tôi không nghĩ rằng một hàm riêng biệt là một ý tưởng tồi) là không cần thiết nhưng những lần khác nó không đơn giản như vậy ngay cả khi có những cách khác.
Pryftan

2

Đó là một phạm vi khối được đánh dấu bằng {}dấu ngoặc nhọn. Nó thường được sử dụng để đánh dấu khu vực lưu trữ tự động . Trong trường hợp của bạn, nó dường như không làm được gì vì vòng lặp for có phạm vi riêng trong C ++ tiêu chuẩn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.