Là nó tốt để xác định một biến trong một vòng lặp? [đóng cửa]


15

Người hướng dẫn của tôi đã từng nói với tôi rằng tôi không nên xác định một biến trong vòng lặp , nhưng thật lòng tôi vẫn không hiểu tại sao.

Những bất lợi của điều đó là gì?

Có ai có thể giải thích điều đó cho tôi không?


7
Ngôn ngữ lập trình nào được giảng viên của bạn dạy?
Brian

2
Nếu bạn xác định một biến có kiểu không nguyên thủy trong một vòng lặp, chương trình của bạn có thể sẽ không cần gọi hàm tạo của nó mỗi lần qua vòng lặp. Nếu bạn chỉ cần xác định nó một lần bên ngoài vòng lặp, hãy làm điều đó.
Brandin

17
Khi bạn có sự nhầm lẫn như vậy về những gì một người hướng dẫn nói, tài nguyên tốt nhất là hỏi người hướng dẫn. Họ có thể cung cấp cho bạn thông tin liên lạc qua lại dày đặc mà trang web Hỏi & Đáp không thể cung cấp.

1
Sao chép chéo trang: Sự khác biệt giữa khai báo biến trước hoặc trong vòng lặp? (và tất nhiên là nhiều, rất nhiều bản sao trên trang web đó cho một câu hỏi cơ bản như vậy (bao gồm cả những câu hỏi chỉ nói về C ++)).
Peter Mortensen

2
Lời khuyên đó là cụ thể cho một bối cảnh. Là một vấn đề của phong cách cá nhân, tôi thích khai báo các biến của mình consttrừ khi có lý do để không (một thói quen từ lập trình chức năng). Hoặc tôi sẽ không sửa đổi chúng và trình tối ưu hóa sẽ phát hiện khi chúng không cần thiết, hoặc tôi sẽ và tôi đã ngăn chặn một lỗi nghiêm trọng. Khi các giá trị trung gian không đổi đó đặc trưng cho một lần lặp của vòng lặp, điều đó có nghĩa là khai báo chúng bên trong vòng lặp. Tuy nhiên, lần khác khi bạn cần khai báo các biến bên ngoài vòng lặp là khi bạn sẽ đề cập đến chúng bên ngoài vòng lặp; ví dụ: kết quả bạn đang lưu trữ
Davislor

Câu trả lời:


43

Nó không phải là một vấn đề để xác định một biến trong một vòng lặp. Trên thực tế, đó là một thực tiễn tốt, vì các định danh nên được giới hạn trong phạm vi nhỏ nhất có thể.

Điều tồi tệ là chỉ định một biến trong vòng lặp nếu bạn cũng có thể gán nó một lần trước khi vòng lặp chạy. Tùy thuộc vào mức độ phức tạp của phía bên phải của bài tập, điều này có thể trở nên khá tốn kém và thậm chí có thể chi phối thời gian chạy của vòng lặp. Nếu bạn viết một vòng lặp sử dụng cùng một giá trị được tính toán trong tất cả các lần lặp, bạn chắc chắn nên tính toán nó trên vòng lặp - điều đó quan trọng hơn việc giảm thiểu phạm vi của nó.

Để làm rõ: miễn là compute()luôn trả về cùng một giá trị, điều này

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

thông minh hơn thế này:

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

2
Làm thế nào bạn sẽ xác định một biến trong vòng lặp và gán nó trước vòng lặp?
Người đàn ông đeo mặt nạ

6
@MaskedMan, tôi nghĩ bạn đang hiểu lầm. Kilian có nghĩa là gì nếu bạn có một biến được gán cùng một giá trị trong mỗi lần lặp của một vòng lặp, ví dụ, cùng một biến ngày được đặt thành 1/1/1900, biến phải được khai báo và giá trị phải được gán trước vòng lặp.
ps2goat

2
Tôi không nghĩ rằng đã có một trình biên dịch được viết trong hai mươi năm qua (bên ngoài khóa học trình biên dịch dưới đại học) sẽ không hình dung ra bạn đang gán cùng một giá trị cho mỗi lần lặp và chuyển nhiệm vụ đó ra khỏi vòng lặp.
TMN

14
@tmn: Không bao giờ để trình biên dịch làm những gì bạn có thể tự làm một cách tầm thường với độ rõ mã lớn hơn.
Robert Harvey

10
@TMN, không nhất thiết. Việc tối ưu hóa đó chỉ khả thi nếu trình biên dịch có thể chứng minh rằng tính toán không có tác dụng phụ.
Paul Draper

16

Các loại phức tạp có các hàm tạo và hàm hủy không tầm thường.

Chúng sẽ được gọi ở đầu và cuối của thân vòng lặp (khi nó được khởi tạo và đi ra khỏi phạm vi). Nếu việc khởi tạo là tốn kém như nó cần phải phân bổ một số bộ nhớ thì điều đó nên tránh.

Tuy nhiên đối với các loại tầm thường mà không có vấn đề. Việc phân bổ và giải quyết chính nó chỉ là thêm và trừ một giá trị từ con trỏ ngăn xếp. (sẽ được tối ưu hóa)


cảm ơn, chính xác câu trả lời tôi đang tìm kiếm!
gebbissimo

6

Chà, lời khuyên của anh ta hơi quá đơn giản (đó là một cách nói nhẹ nhàng ).
Theo sau nó bao gồm tất cả các cách từ một ý tưởng tốt về người quan tâmý tưởng xấu đến không thể .

  1. Bạn nên theo dõi nó bất cứ khi nào sử dụng lại rẻ hơn so với phá hủy cái cũ và tạo cái mới.

    #include <iostream>
    #include <string>
    
    int main() {
        std::string s; // Don't needlessly free the buffer
        while ((std::cin >> s))
            std::cout << s;
    }
  2. Bạn nên tránh xa nó như một vấn đề về phong cách khi nó không quan trọng đối với hiệu suất.

    #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. Bạn thực sự nên tránh xa nó khi nó có hiệu suất kém hơn hoặc ngữ nghĩa sai.

    #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. Bạn không thể theo dõi nó khi loại được sử dụng cho phép không hoán đổi, cũng không chuyển nhượng cũng không gán sao chép.

    #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
Tùy thuộc vào định nghĩa của bạn về "trong một vòng lặp", 1 có thể được thay đổi thành for (std::string s; std::cin >> s;) ...và vẫn là "bên ngoài"
Caleth
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.