2012-06-27 29 views
10

Tôi đang tạo một lớp C++ 11 tạo ra một lượng lớn dữ liệu. Dữ liệu đó hiện đến từ một cơ sở dữ liệu và nó không thể hoàn toàn phù hợp với bộ nhớ. Tôi muốn cung cấp cho người dùng một trình lặp có hoạt động giống như các trình lặp STL thông thường, nhưng điều đó sẽ rất lười. Chính xác hơn, tôi sẽ có thể làm một việc như thế:Làm thế nào tôi có thể tạo trình vòng lặp lười biếng của riêng mình?

for (auto& item : big_bunch_of_data) { 
    do_stuff_with(item); 
} 

Với mục được lấy từ cơ sở dữ liệu chỉ tại mỗi lần lặp. Nếu tôi đúng, cú pháp mới này là đường cho

for (stuff::iterator it = big_bunch_of_data.begin();it != big_bunch_of_data.end();it++) { 
    do_stuff_with(*it); 
} 

Liệu nó có nghĩa là bằng cách cung cấp begin, endoperator++, tôi có thể có hành vi mong muốn? Và, những phương pháp này phải làm gì? Ý tôi là, tôi có thể làm cho họ lười biếng mà không phá vỡ công cụ?

+1

_ "Dữ liệu đó xuất phát từ một cơ sở dữ liệu và không thể hoàn toàn phù hợp với bộ nhớ", vì vậy, không biết cơ sở dữ liệu của bạn khó đưa ra lời khuyên tốt hơn ... nhưng hãy nhớ rằng nhiều cơ sở dữ liệu SQL cung cấp các cơ chế lặp nội bộ của riêng chúng dạng _cursors_ có thể được sử dụng cho bạn ở đây. – Rook

+1

Tôi đang sử dụng sqlite, nhưng điều đó có thể thay đổi trong tương lai và tôi không muốn để lộ con trỏ thô tới người dùng mã của tôi, đó là lý do tôi cố gắng đóng gói nó khá tốt (và có, đã lười) API. – Fabien

Trả lời

11

Hầu như; trình biên dịch sẽ xem xét ở một vài nơi khác để bắt đầu và kết thúc vòng lặp nếu nó không thể tìm thấy các phương thức begin hoặc end trên lớp container; đây là cách dựa trên phạm vi cho các vòng hoạt động trên mảng, không có các thành viên beginend. Nó cũng sẽ tìm kiếm các chức năng miễn phí beginend bởi ADL và cuối cùng là std::beginstd::end, do đó, có rất nhiều cơ hội để trang bị thêm dải dựa trên hỗ trợ vòng lặp cho các vùng chứa hiện có. Phần 6.5.4 trình bày chi tiết.

Đối với câu hỏi khác của bạn, trình lặp hoàn toàn có thể lười biếng! Một ví dụ tốt là std::istream_iterator là lười khi đọc đầu vào từ bảng điều khiển.

Yêu cầu sử dụng trình lặp trong một vòng lặp for là nó phải đáp ứng loại vòng lặp đầu vào đầu vào, được mô tả trong phần 24.2.3; các hoạt động bắt buộc cho danh mục đó là !=, unary * và trước và sau tăng thêm ++.

Để cho ngôn ngữ biết rằng bạn đã tạo một trình lặp đầu vào, bạn nên kế thừa từ std::iterator<std::input_iterator_tag, T, void, T *, T &> trong đó T là loại giao dịch lặp của bạn (phần 24.4.3).

+3

Thực ra, không. Nó sử dụng các hàm thành viên '.begin()' trực tiếp. Và nếu không có các thành viên như vậy được tìm thấy nó sử dụng 'begin' thông qua ADL, không nhất thiết phải' std :: begin'. –

+0

@ R.MartinhoFernandes cảm ơn vì đã làm rõ. – ecatmur

+0

Vâng, cảm ơn, đó là chính xác những gì tôi cần. – Fabien

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