01/10/2018, 15:36

Iterator có khác gì với pointer không?

Cho mình hỏi iterator có khác gì với pointer không? Thực ra ban đầu mình nghĩ iterator là index, nhưng search mạng thì thấy là không phải. (mình lập trình C++, tại liên quan đến vector::begin() nên mình tìm hiểu)

Nguyễn Phạm Anh Quân viết 17:46 ngày 01/10/2018

iterator cũng là pointer nhé! std::vector::begin() và std::vector::end() ( or cbegin(), cend() ) đều trả về iterator ngay tại index đầu và kế cuối (last - 1)
https://www.cs.northwestern.edu/~riesbeck/programming/c++/stl-iterators.html

rogp10 viết 17:39 ngày 01/10/2018
  1. Bạn không thể ++ pointer để duyệt tree được nhưng ++ iterator thì được.
  2. Pointer chỉ trỏ đến đối tượng, còn iter gắn chặt với cấu trúc STL có liên quan. Vì vậy dễ dàng lấy được các iter quan trọng:std::X::begin(), ::(r)end(), ::back().
  3. Có những iterator chỉ đọc, không cho ghi. Xem link phía trên để biết thêm chi tiết.
viết 17:53 ngày 01/10/2018

iterator có khác gì với pointer không?

có khác, bạn vô đây tìm hiểu thêm: http://en.cppreference.com/w/cpp/iterator
.
.
mấy cái này là “khái niệm” - concept, nó na ná với interface nhưng ko phải interface vì nó được dịch lúc compile, trong khi interface được “dịch” lúc chạy chương trình.
.
.
Iterator: là kiểu có thể gọi *it++it, và có copy ctor It it2 = it1;, có toán tử gán: it1 = it2, có hàm hủy, có thể swap được, và có thêm mấy typedef cho mấy kiểu mà nó xài nữa: It::value_type, It::difference_type, It::reference, It::pointer, It::iterator_category

InputIterator: thỏa mãn các khái niệm của Iterator, cộng thêm toán tử so sánh bằng/khác nhau: it1 == it2, it1 != it2, và đặc biệt *it chỉ xài được 1 lần (single pass), deref lần 2 ko được, ví dụ it2 = it1; *it1; /*ok*/ *it2; /*not ok*/. Ví dụ của input iterator là std::istreambuf_iterator: chỉ đọc ký tự trích từ input stream 1 lần, ko đọc được lần thứ 2. Ví dụ để đọc toàn bộ nội dung của 1 file:

std::ifstream f("file.txt");
std::string content((std::istreambuf_iterator<char>(f)),
                     std::istreambuf_iterator<char>());

OutputIterator: thỏa mãn khái nhiệm Iterator, và câu lệnh *it = x; là hợp lệ. (InputIterator ko cần thiết phải gán *it = x;, nếu 1 iterator gán x cho *it được thì nó là OutputIterator)

ForwardIterator: thỏa mãn khái niệm InputIterator, *it xài được nhiều lần (multi pass). Kiểu trả về của *itIt::reference có thể là const T&, hoặc T& nếu iterator này cũng thỏa mãn khái niệm OutputIterator. Ví dụ: con trỏ của danh sách liên kết đơn.

BidirectionalIterator: thỏa mãn khái niệm ForwardIterator, cộng thêm khả năng decrement: --itit--. Ví dụ: con trỏ của danh sách liên kết đôi.

RandomAccessIterator: thỏa mãn khái niệm BidirectionalIterator, cộng thêm khả năng cộng trừ số nguyên: it += n, it -= n, it + n, it - n và so sánh lớn bé: it1 < it2, it1 > it2, it1 <= it2, it1 >= it2. Ví dụ: con trỏ của mảng C, con trỏ của mảng C++ std::array<T>, con trỏ của std::vector<T>, con trỏ của std::deque<T>

ngoài ra còn có khái niệm ContiguousIterator, nó giống hệt RandomAccessIterator, chỉ trừ vector<bool>::iterator là ko thỏa mãn khái niệm ContiguousIterator này. Phải thêm ông này vào chỉ vì thằng vector<bool>… Với vector<T>::iterator, bạn có thể chuyển iterator thành con trỏ bằng cách xài T* ptr = &*it;, chỉ duy nhất có ông vector<bool>::iterator là ko thể lấy con trỏ bool* như vậy được, nên mới phải đẻ ra khái niệm mới ContiguousIterator này. Edit: std::deque<T>::iterator với T bất kì cũng ko thỏa mãn khái niệm ContiguousIterator.

tương lai ko còn xài khái niệm iterator nữa mà xài khái niệm range gì đó @_@

Bài liên quan
0