1. Vấn đề nó giải quyết
Iterator category mô tả cách di chuyển và truy cập được hỗ trợ; quy tắc invalidation cho biết khi nào sửa container làm iterator cũ không còn dùng được. Nó làm ràng buộc quan trọng hiện rõ thay vì bắt người đọc đoán. Bài chỉ giữ phần cốt lõi C++11 vừa đủ cho một ngày tập trung.
2. Kiến thức cần có
Kiến thức Ngày 39, cùng biến, hàm và cách đọc output đã học trước đó.
3. Ý tưởng cốt lõi
Mental model: Iterator category mô tả cách di chuyển và truy cập được hỗ trợ; quy tắc invalidation cho biết khi nào sửa container làm iterator cũ không còn dùng được. Hãy xác định giá trị hoặc trạng thái liên quan, ai sở hữu nó và quy tắc tác động lúc compile hay lúc chạy.
4. Cú pháp tối thiểu
auto it = v.begin(); v.reserve(3); // capacity decisions affect validity5. Cách nó hoạt động
Ví dụ tạo dữ liệu nhỏ, cố định và không cần nhập bàn phím.
C++11 hoặc contract thư viện chuẩn áp dụng quy tắc hôm nay.
Chương trình in kết quả quan trọng để đối chiếu với mã nguồn.
6. Lỗi thường gặp
Giải tham chiếu iterator đã invalidated gây undefined behavior dù địa chỉ cũ có vẻ vẫn chứa giá trị mong đợi.
7. Khi nào nên dùng
Nên dùng khi chọn thuật toán và giữ trạng thái duyệt qua thay đổi container.
Tránh dùng khi nó che ownership, lifetime, kiểu, thứ tự hoặc chi phí.
8. Ví dụ đơn giản
Vector đã reserve giữ iterator hợp lệ qua một lần chèn, còn iterator list được di chuyển bằng std::advance trung lập theo category. File .cpp dùng dữ liệu cố định và không thêm abstraction ngoài chủ đề.
Mã mẫu hoàn chỉnh
Tệp mã nguồn
cpp11/40_iterator_categories_invalidation/main.cpp
#include <iostream>
#include <iterator>
#include <list>
#include <vector>
int main() {
std::vector<int> numbers;
numbers.reserve(3);
numbers.push_back(10);
numbers.push_back(20);
std::vector<int>::iterator first = numbers.begin();
numbers.push_back(30); // no reallocation: reserved capacity is 3
std::cout << "vector_first=" << *first << '\n';
std::list<int> linked{4, 5, 6};
std::list<int>::iterator middle = linked.begin();
std::advance(middle, 1); // works for non-random-access iterators
std::cout << "list_middle=" << *middle << '\n';
// Another vector insertion may reallocate and invalidate first.
}
9. Điều cần nhớ
Tính năng nằm trong phạm vi C++11 của lộ trình này.
Hiểu hệ quả về lifetime, ownership, kiểu và thứ tự trước khi dùng.
Compile với cảnh báo và ưu tiên cách viết nhỏ nhất làm quy tắc hiện rõ.
10. Câu hỏi tự kiểm tra
Dễ — Iterator category và iterator invalidation mô tả hai điều gì khác nhau? Vì sao cần kiểm tra iterator cũ sau khi
std::vectorcấp phát lại vùng nhớ?Trung bình — Đọc ví dụ nhỏ ở trên. Chương trình sẽ in giá trị hoặc trạng thái nào, và quy tắc nào tạo ra kết quả đó?
Khó — Tìm và giải thích lỗi tinh tế trong tình huống sau: Giải tham chiếu iterator đã invalidated gây undefined behavior dù địa chỉ cũ có vẻ vẫn chứa giá trị mong đợi. Cách sửa nhỏ nhất nhưng an toàn trong C++11 là gì?