2010-03-24 19 views
22

Tôi biết đây có lẽ là câu hỏi ngớ ngẩn .. Khi nào tôi cần viết trình lặp của riêng mình? Là nó chỉ khi thiết kế lớp container của riêng tôi? Có lần nào khác khi tôi muốn tạo trình lặp của riêng mình không?Khi nào cần viết một trình lặp?

Ví dụ sẽ được chiếm đoạt.

-Jon

+7

Từ những gì các câu trả lời cho biết, bạn sẽ nghĩ rằng tất cả mọi người ra khỏi đó đã sốt sắng viết vòng lặp! Nói cá nhân, tôi nghĩ rằng tôi có thể đã làm như vậy có lẽ hai lần trong sự nghiệp C++ của tôi. –

+3

Như được hiển thị trong các câu trả lời, có những lúc nó có ý nghĩa để thực hiện một iterator tùy chỉnh, nhưng những lần đó là hiếm. Nếu lớp container của bạn được xây dựng trên đầu trang của một container STL, nó có thể thích hợp chỉ để lộ các trình vòng lặp của container bên dưới chứ không phải là của riêng bạn. –

+1

Chủ yếu là tôi nghĩ mọi người đề cập đến các trình vòng lặp có sẵn trong một số thư viện. Ví dụ: xem http://www.boost.org/doc/libs/1_42_0/libs/iterator/doc/index.html#specialized-adaptors. Không cần phải tự mình thực hiện;) – UncleBens

Trả lời

2

Bạn cần viết trình lặp riêng cho lớp chứa của chính bạn hoặc nếu bạn cần hành vi không chuẩn khi lặp qua vùng chứa tiêu chuẩn.

3

Khi bạn có một lớp học (rất có thể là một vùng chứa) và bạn muốn cho phép người dùng của bạn duyệt nó một cách thuận tiện mà không cần tiết lộ chi tiết triển khai, bạn sẽ muốn tạo một trình lặp. Điều này thậm chí còn đúng hơn khi bạn có một gia đình các lớp (một lần nữa, rất có thể là các thùng chứa) và bạn muốn cung cấp cho người dùng của mình một giao diện lặp/truyền tải đồng bộ cho tất cả chúng, ngay cả khi triển khai của chúng rất khác nhau (tức là danh sách liên kết so với một mảng).

7

Có, có những lúc khác. Đối với một vài ví dụ:

  1. Trình lọc_ chỉ trả về tập hợp con đã lọc của các mục trong vùng chứa.
  2. Trình vòng lặp lựa chọn chỉ trả lại một phần của đối tượng.
  3. Trình tạo dấu ngắt dòng đặt dấu phân cách trước hoặc giữa các mục, thay vì sau chúng.
1

tôi có thể nhìn thấy hai trường hợp bạn muốn tạo một iterator mới:

  • Đối với lớp container của riêng bạn (như bạn chỉ ra cho mình).
  • Trình lặp với hành vi tùy chỉnh cho lớp chứa hiện tại. Ví dụ STL có backwards iterators. Có thể bạn muốn một số every_3rd_iterator chỉ trả về mọi phần tử thứ ba? Một trình vòng lặp như vậy có thể sẽ được thực hiện như một bộ điều hợp xung quanh một trình lặp hiện có.
5

Bất cứ khi nào bạn cần lặp qua chuỗi dữ liệu và trình lặp không được xác định phù hợp với nhu cầu của bạn.

Thông thường, bạn sử dụng trình vòng lặp để chuyển vùng chứa, nhưng đó là cách xa chỉ sử dụng.

Trình lặp cũng có thể duyệt qua kết quả của truy vấn cơ sở dữ liệu hoặc đọc đầu vào từ luồng (std::istream_iteratorstd::istreambuf_iterator đã làm điều này, tuy nhiên) hoặc có thể bạn cần một chiến lược hoặc trật tự truyền tải đặc biệt. Có lẽ bạn muốn lặp lại "mọi thành viên của vectơ này, có chỉ mục chia hết cho bốn" hoặc "mọi chữ cái viết hoa trong chuỗi này" hoặc bất kỳ điều gì khác bạn có thể nghĩ đến.

+2

+1: một số ví dụ khác thoát khỏi các câu trả lời khác: 'boost :: filesystem :: directory_iterator' không lặp lại một vùng chứa, mà là một thư mục. 'pqxx :: result :: iterator' lặp qua kết quả từ một truy vấn tới một DB,' boost :: asio :: tcp :: resolver :: iterator' lặp lại trên các điểm cuối tcp ... không có gì trong số đó chính xác là một thùng chứa, nhưng họ sử dụng thành ngữ iterator. –

+0

Các kết quả phù hợp trong chuỗi tìm kiếm/tìm kiếm regex, v.v. – UncleBens

1

Ngoài bộ lặp và bộ chọn vòng lặp, thời gian duy nhất tôi đã viết trình lặp trong C++ là để có được các lớp chứa của bên thứ ba để chơi tốt với các thuật toán stl.Ví dụ

  • Một iterator truy cập ngẫu nhiên cho một chuỗi CORBA
  • Một Inserter lại cho một chuỗi CORBA
  • Một iterator hai chiều cho XML Dom, điều này chuyển đổi một nút dom đến một iterator mà cho phép tôi sử dụng foreach và biến đổi trên các nút anh chị em ruột.

Nói chung tôi không thích viết các trình vòng lặp vì chúng rất khó, có rất nhiều thứ cần quan tâm. Tuy nhiên, nhiệm vụ này được thực hiện dễ dàng hơn nhiều với thư viện boost iterator.

+1

Tôi thực sự vừa tải xuống phiên bản ngày hôm qua. Bây giờ nếu tôi chỉ có thể nhận được thư viện riêng để xây dựng .. – Jon

+0

Xin chào Jon, tôi đã đấu tranh để biên soạn các thư viện tăng trước. Tuy nhiên chỉ có một số thư viện phải được xây dựng. Hầu hết các thư viện chỉ là tiêu đề và không cần phải xây dựng chỉ bao gồm.Thư viện trình lặp là một trong những – iain

0

Bạn cũng có thể muốn sử dụng chúng để lặp qua chuỗi số, chẳng hạn như số Fibonacci hoặc có thể là số nguyên tố. Đây có thể được thực hiện theo những cách khác, có lẽ dễ dàng hơn, nhưng có thể đôi khi việc sử dụng trình lặp cho những thứ như vậy có ý nghĩa.

2

Trình vòng lặp thực hiện có thể vô cùng hữu ích và tôi đã làm như vậy khá thường xuyên. Trình lặp là một khái niệm đơn giản mà mọi người đều biết cách sử dụng. Iterator cho phép bạn sử dụng các thuật toán STL.

Thông thường, bạn có thể thực hiện lặp để đơn giản hóa việc sử dụng các API hệ điều hành thường được sử dụng như Windows' FindNextFile

Khi bạn viết một file_iterator (đã tồn tại trong tăng), bạn đột nhiên có thể làm:

file_iterator itBegin; // initialize appropriately 
file_iterator itEnd; 
std::vector<HANDLE> vecFiles(itBegin, itEnd); 

để có danh sách xử lý cho tất cả các tệp phù hợp. Nếu không có trình lặp, các cuộc gọi API cần thiết sẽ làm cho mã của bạn khó đọc hơn.

Hãy suy nghĩ về vòng lặp là khái niệm đơn giản cho phép bạn viết những gì bạn thực sự có ý nghĩa để nói và trừu tượng đi các chi tiết gritty nitty. Nếu bạn phải thực hiện một thuật toán phức tạp mà khó hiểu, bạn muốn giảm sự lộn xộn của mã.

Nếu bạn có cấu trúc hai chiều, ví dụ: std :: vector < std :: vector>, nói cách khác là một bảng, trong đó mỗi vector bên trong được yêu cầu có cùng độ dài, bạn có thể cần phải lặp qua mọi phần tử thứ n của các vectơ bên trong. Nếu điều này xảy ra thường xuyên, mã của bạn có thể trở nên đơn giản hơn rất nhiều khi bạn triển khai một trình lặp thay vì lan truyền các vòng lặp lồng nhau trong suốt mã.

Các vấn đề liên quan