Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

Iterator Invalidation ใน C++

คำอธิบาย

Iterator Invalidation** เกิดขึ้นเมื่อ iterator ชี้ไปที่ตำแหน่งที่ไม่ถูกต้องอีกต่อไป เนื่องจาก container เปลี่ยนแปลงขนาดหรือจัดสรรหน่วยความจำใหม่

กรณีที่พบบ่อย

  • vector: push_back/insert/erase อาจทำให้ reallocate → iterator ทั้งหมด invalid
  • list/deque: insert/erase invalidates เฉพาะ iterator ที่ถูกลบ
  • map/set: insert/erase invalidates เฉพาะ iterator ที่ถูกลบ

ตัวอย่างปัญหา

#include <bits/stdc++.h>
using namespace std;

int main() {
    vector<int> v = {1, 5, 10, 15, 20};
    
    // ผิด: modify vector ขณะ iterate
    for(auto it = v.begin(); it != v.end(); it++) {
        if(*it == 5) {
            v.push_back(-1); // อาจ reallocate → it invalid!
        }
    }
    
    // ถูกต้อง: ใช้ index หรือเก็บค่าก่อน
    for(size_t i = 0; i < v.size(); i++) {
        if(v[i] == 5) v.push_back(-1); // ปลอดภัยกว่า (แต่ size เปลี่ยน)
    }
    
    // หรือใช้ erase-remove idiom
    // v.erase(remove(v.begin(), v.end(), 5), v.end());
    
    for(int x : v) cout << x << " ";
    return 0;
}

แนวทางป้องกัน

  1. หลีกเลี่ยงการ modify container ขณะ iterate (ยกเว้น erase ที่คืน iterator ใหม่)
  2. ใช้ index-based loop แทน iterator
  3. เก็บค่าที่ต้องการลบ/แก้ไขไว้ แล้วทำในภายหลัง
  4. ใช้ erase ที่คืน iterator ถัดไป (C++11+)