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)
Iterator có khác gì với pointer không?
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
- Bạn không thể ++ pointer để duyệt tree được
nhưng ++ iterator thì được.
- 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::(r)begin()
,::(r)end()
,::back()
. - Có những iterator chỉ đọc, không cho ghi. Xem link phía trên để biết thêm chi tiết.
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
và ++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 *it
là It::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: --it
và it--
. 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ì đó @_@