2009-08-07 4 views
21

Chỉ là một câu hỏi nhanh.đánh giá điều kiện vòng lặp

Tôi có một vòng lặp mà trông như thế này:

for (int i = 0; i < dim * dim; i++) 

là điều kiện trong một vòng lặp for tái đánh giá trên mỗi vòng lặp?

Nếu vậy, nó sẽ hiệu quả hơn để làm một cái gì đó như thế này ?:

int dimSquare = dim * dim; 
for (int i = 0; i < dimSquare; i++) 

Cảm ơn

-Faken

Trả lời

32

Nói chung, nếu bạn thay đổi giá trị "mờ" bên trong vòng lặp của bạn, nó sẽ được đánh giá lại mỗi lần. Nhưng kể từ đó không phải là trường hợp trong ví dụ của bạn, một trình biên dịch phong nha sẽ tối ưu hóa mã của bạn và bạn sẽ không thấy bất kỳ sự khác biệt về hiệu suất.

+0

Xin lỗi người đã trả lời rất lâu, nhưng câu trả lời này giải thích mọi thứ cho tôi một cách rõ ràng và súc tích. – Faken

+3

Nhưng đừng quên đưa ra ý kiến ​​của bdonlan về việc sử dụng các biến cục bộ để điều khiển vòng lặp - người dân địa phương giúp mọi người dễ dàng tối ưu hóa các trình biên dịch vì khả năng hiển thị của chúng bị hạn chế (điều này cũng có thể giúp người đọc hiểu, không chỉ tối ưu hóa trình biên dịch). –

+0

Tôi sẽ không xin lỗi nếu tôi là bạn. Điều này cho bdonlan một shot tốt tại huy hiệu "populist", với 9 phiếu bầu nhiều hơn (tại thời điểm viết bài) và nếu Lulu nhận thêm 8 :-) –

-4

trình biên dịch sẽ precompute giá trị của Dim * Dim trước Loop bắt đầu

+0

Trừ khi Dim có thể được sửa đổi bên trong vòng lặp. –

+0

Vì vậy, những gì bạn nói là trong một vòng lặp for, ngay cả khi giá trị của thay đổi mờ trong vòng lặp, vòng lặp sẽ chạy cho đến khi giá trị biên dịch trước được đạt tới? hoặc chương trình sẽ đánh giá lại nó khi thay đổi mờ giữa chừng vòng lặp? – Faken

+1

@Faken, nếu có bất kỳ khả năng nào của Dim thay đổi, trình biên dịch sẽ đánh giá lại nó _every_ loop. – bdonlan

44

Có, ngữ nghĩa nó sẽ được đánh giá trên mỗi vòng lặp. Trong một số trường hợp, trình biên dịch có thể có thể tự động loại bỏ điều kiện khỏi vòng lặp - nhưng không phải lúc nào cũng vậy. Đặc biệt:

void foo(const struct rect *r) { 
    for (int i = 0; i < r->width * r->height; i++) { 
    quux(); 
    } 
} 

Trình biên dịch sẽ không thể để di chuyển nhân ra trong trường hợp này, như đối với tất cả nó biết quux() đổi r.

Nói chung, thường chỉ các biến cục bộ mới đủ điều kiện để nâng biểu thức ra khỏi vòng lặp (giả sử bạn không bao giờ lấy địa chỉ của chúng!). Mặc dù trong một số điều kiện cấu trúc các thành viên có thể đủ điều kiện, có rất nhiều thứ có thể khiến trình biên dịch giả định mọi thứ trong bộ nhớ đã thay đổi - chỉ viết về bất kỳ con trỏ nào hoặc gọi hầu như bất kỳ hàm nào. Vì vậy, nếu bạn đang sử dụng bất kỳ người không phải là người dân địa phương ở đó, tốt nhất là giả sử tối ưu hóa sẽ không xảy ra.

Điều đó nói rằng, nói chung, tôi muốn chỉ khuyên bạn nên chủ động di chuyển có khả năng mã đắt tiền ra khỏi tình trạng này nếu nó hoặc là:

  • Không tổn thương khả năng đọc để làm như vậy
  • Rõ ràng sẽ mất một rất thời gian dài (ví dụ: truy cập mạng)
  • Hoặc hiển thị dưới dạng điểm phát sóng trên hồ sơ.
+6

Lưu ý rằng r có thể là 'const struct rect *' trong ví dụ của bạn, và trình biên dịch * vẫn * sẽ không được phép giả định rằng quux() không bằng cách nào đó sửa đổi các thành viên dữ liệu của nó thông qua một bí danh. Nó thường được giả định rằng const kích hoạt tất cả các cách tối ưu hóa trình biên dịch, nhưng nó không phải là khá đơn giản như người ta có thể nghĩ đầu tiên. –

+0

@onebyone: Thật vậy. Hạn chế có thể giúp đỡ ở đây, tuy nhiên. – bdonlan

+0

Yep, cho trình biên dịch C++ cũng là trình biên dịch C99 và do đó hỗ trợ giới hạn. Và các quy tắc bí danh nghiêm ngặt giúp "viết cho bất kỳ con trỏ nào", nhưng không phải với "gọi hầu như bất kỳ hàm nào". Nội tuyến sẽ giúp với các chức năng. –