Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Vô hiệu hóa Iterator (Iterator Invalidation) trong C++

Trong C++, có các container như vector, list, set, map... Để duyệt, ta dùng iterator. Cần cẩn thận khi dùng iterator. Khi duyệt container, đôi khi iterator bị vô hiệu hóa. Nếu hình dạng, kích thước thay đổi, có thể gặp vấn đề này. Ví dụ sau minh họa vấn đề vô hiệu hóa.

Ví dụ Code

#include <iostream>
#include <vector>
using namespace std;

int main() {
  vector<int> vec{11, 55, 110, 155, 220};
  for (auto it = vec.begin(); it != vec.end(); it++)
    if ((*it) == 110)
      vec.push_back(89); // chèn giá trị mới khi đang duyệt vector
  for (auto it = vec.begin(); it != vec.end(); it++)
    cout << (*it) << " ";
}

Kết quả

11 55 110 155 220 89 89

Chương trình này có thể cho kết quả khác nhau. Vector chưa định nghĩa kích thước trước. Khởi tạo một số giá trị. Khi duyệt, ta thêm một giá trị. Nếu vector hết chỗ, nó cấp phát khối bộ nhớ mới tại runtime, sao chép tất cả phần tử. Nhưng iterator vẫn trỏ địa chỉ cũ. Điều này gây vô hiệu hóa.

Xem một số quy tắc về vô hiệu hóa iterator:

Chèn (Insertion) Xóa (Erasure) Thay đổi kích thước (Resizing)
Vector Tất cả iterator trỏ đến phần tử trước điểm chèn không ảnh hưởng, các iterator khác bị vô hiệu hóa. Nếu kích thước vector tăng, tất cả iterator bị vô hiệu hóa. Tất cả iterator và tham chiếu sau điểm xóa bị vô hiệu hóa. Tương tự chèn hoặc xóa.
Deque Tất cả iterator và tham chiếu bị vô hiệu hóa nếu phần tử chèn không phải ở cuối deque. Nếu xóa từ vị trí nào khác cuối, tất cả iterator bị vô hiệu hóa. Tương tự chèn hoặc xóa.
List Tất cả iterator và tham chiếu không bị ảnh hưởng. Chỉ iterator/tham chiếu trỏ đến phần tử bị xóa mới bị ảnh hưởng. Tương tự chèn hoặc xóa.
Set, map, multiset, multimap Tất cả iterator và tham chiếu không bị ảnh hưởng. Chỉ iterator/tham chiếu trỏ đến phần tử bị xóa mới bị ảnh hưởng. ----