Động cơ trung tâm để giới thiệu một sentinel là có rất nhiều hoạt động lặp được hỗ trợ nhưng thường không bao giờ cần thiết cho end-iterator end()
. Ví dụ, hầu như không có bất kỳ điểm nào trong dereferencing nó thông qua *end()
, trong incrementing nó qua ++end()
, và như vậy (*).
Ngược lại, cách sử dụng chính của end()
chỉ đơn thuần là so sánh nó với một trình biến đổi it
để báo hiệu liệu it
có ở cuối thứ mà nó chỉ lặp lại hay không. Và, như thường lệ trong lập trình, các yêu cầu khác nhau và ứng dụng khác nhau đề xuất một loại mới.
Thư viện dãy-v3 biến quan sát này thành một giả định (được thực hiện thông qua một khái niệm): nó giới thiệu một kiểu mới cho end()
và chỉ yêu cầu nó tương đương với trình lặp tương ứng - nhưng không yêu cầu các thao tác lặp thông thường). Loại mới này của end()
được gọi là sentinel.
Lợi thế chính ở đây là trừu tượng thu được và phân tách mối quan tâm tốt hơn, dựa trên đó trình biên dịch có thể thực hiện tối ưu hóa tốt hơn. Trong mã, ý tưởng cơ bản là điều này (đây chỉ là giải thích và không liên quan gì đến thư viện phạm vi-v3):
struct my_iterator; //some iterator
struct my_sentinel
{
bool is_at_end(my_iterator it) const
{
//here implement the logic when the iterator is at the end
}
};
auto operator==(my_iterator it, my_sentinel s) //also for (my_sentinel s, my_iterator it)
{
return s.is_at_end(it);
}
Xem tóm tắt? Bây giờ, bạn có thể thực hiện bất kỳ kiểm tra mà bạn muốn trong is_at_end
chức năng, ví dụ:
- dừng bao giờ (nhận được một phạm vi vô hạn)
- dừng sau
N
increments (để có được một loạt tính)
- dừng khi một
\0
gặp phải, tức là *it = '\0'
(để lặp qua chuỗi C)
- dừng khi đó là 12'o đồng hồ (để ăn trưa), v.v.
Hơn nữa, liên quan đến hiệu suất, người ta có thể sử dụng thông tin thời gian biên dịch trong séc (ví dụ: nghĩ về số N
ở trên làm thông số biên dịch). Trong trường hợp này, trình biên dịch có thể có khả năng tối ưu hóa mã tốt hơn.
(*) Lưu ý rằng điều này không có nghĩa là nói chung không sử dụng cho loại hoạt động này.Ví dụ: --end()
có thể hữu ích ở một số nơi, xem ví dụ: this question. Tuy nhiên, dường như có thể thực hiện thư viện chuẩn mà không có những thư viện này - đây là thư viện phạm vi-v3 đã làm.
phạm vi zip là gì? – Walter
@walter thêm chú thích – Yakk
Hmm.Nhưng một trình vòng lặp zip không thể là một RandomAccessIterator, vì tham chiếu 'của nó không giống với' value_type & '. có thể không hoạt động (như bạn đã nói [chính mình] (http://stackoverflow.com/a/32871002/1023390)) Vì vậy, nó là gì tốt cho? – Walter