2009-10-28 26 views
10

Thực hiện cuộc gọi xóa trong std :: đặt trình vòng lặp không hợp lệ? Như tôi đã làm dưới 5 từ dòng cuối cùng ..? nếu có cách nào tốt hơn để xóa tất cả các yếu tố từ bộ là những gìhiệu lực của trình lặp, sau khi xóa() gọi trong std :: set

class classA 
{ 
public: 
    classA(){}; 
    ~classA(){}; 
}; 
struct structB 
{ 
}; 

typedef std::set <classA*, structB> SETTYPE;   
typedef std::map <int, SETTYPE>MAPTYPE; 

int __cdecl wmain (int argc, wchar_t* pArgs[]) 
{ 
    MAPTYPE mapObj; 
    /* 
     ... 
     .. Some Operation Here 
     ... 
     */ 
    for (MAPTYPE::iterator itr1=mapObj.begin(); itr1!=mapObj.end(); itr1++) 
    {  
     SETTYPE li=(*itr1).second; 
     for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();itr2++) 
     { 
      classA *lt=(classA*)(*itr2); 
      li.erase(itr2); 
      delete lt; // Does it invalidate Iterator ? 
     } 
    } 
} 
+2

typedef std :: set SETTYPE; Tôi không chắc chắn lý do tại sao bạn cho StructB làm đối số mẫu thứ hai cho std :: set. std :: set chỉ giữ một giá trị (không có khóa nào được đặt là có bản đồ), đối số mẫu thứ hai được sử dụng để cung cấp hàm functor so sánh cho tập hợp (std :: less by default) –

Trả lời

2

Vì bạn đang chỉ rõ ràng xóa mọi phần tử của bộ này, bạn chỉ có thể làm:

for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();itr2++) 
    { 
      classA *lt=(classA*)(*itr2); 
      delete lt; 
    } 
    li.clear(); // clear the elements 
+0

thx reko_t, cách này giải quyết vấn đề – Satbir

41

Từ tiêu chuẩn 23.1.2

Thành viên chèn sẽ không ảnh hưởng đến tính hợp lệ của trình lặp và tham chiếu đến vùng chứa và thành viên xóa sẽ chỉ vô hiệu hóa trình lặp và tham chiếu đến phần tử đã xóa.

EDIT

Trong trường hợp của bạn itr2 không còn giá trị sau khi xóa nên incrementing nó gây ra hành vi không xác định. Trong trường hợp này bạn có thể làm theo lời khuyên reko_t, nói chung, bạn có thể thử này:

for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();) 
{ 
    classA *lt=(classA*)(*itr2); 
    li.erase(itr2++); 
    delete lt; 
} 

mà sẽ tăng iterator trước loại bỏ nó là giá trị trước đó từ bộ.
BTW. itr2 không bị vô hiệu hóa bởi delete lt;, nhưng bằng cách li.erase(itr2);

+3

Vì điều này trả lời Google của tôi "không đặt xóa iterator invalidate", đây là câu trả lời yêu thích của tôi – Chance

+0

câu trả lời yêu thích của tôi, quá! – Micka

7

Xóa là ok.

Vấn đề là bạn xóa - và do đó làm mất hiệu lực - itr2, nhưng sử dụng nó để lặp vòng lặp.

i.a.w. sau lần xóa đầu tiên, ++itr2 có kết quả không xác định.

Các mô hình tôi sử dụng trong tình huống này là:

while(itr2 != end()) 
{ 
    iterator toDelete = itr2; 
    ++itr2; // increment before erasing! 
    container.erase(toDelete); 
} 

Một số impls STL phi tiêu chuẩn có xóa trả lại lặp tiếp theo, vì vậy bạn có thể làm:

while(itr2 != end()) 
    itr2 = container.erase(); 

đó không phải là di động, Tuy nhiên.


các set<A*,B> lạ, mặc dù - trong một impl tiêu chuẩn, B sẽ là so sánh.

Các vấn đề liên quan