2010-10-15 27 views
22

Cách thích hợp để lặp lại là sử dụng trình vòng lặp. Tuy nhiên, tôi nghĩ rằng bằng cách xóa, trình vòng lặp không hợp lệ.Xóa từ một std :: vector trong khi làm một cho mỗi?

Về cơ bản những gì tôi muốn làm là:

for(iterator it = begin; it != end; ++it) 
{ 
    if(it->somecondition()) 
    { 
    erase it 
    } 

} 

Làm thế nào tôi có thể làm điều này mà không v [i] phương pháp?

Cảm ơn

struct RemoveTimedEvent 
{ 
    bool operator()(const AguiTimedEvent& pX, AguiWidgetBase* widget) const 
    { 
     return pX.getCaller() == widget; 
    } 
}; 

void AguiWidgetContainer::clearTimedEvents(AguiWidgetBase* widget) 
{ 
    std::vector<AguiTimedEvent>::iterator it = std::remove_if(timedEvents.begin(), 
     timedEvents.end(), RemoveTimedEvent()); 
    timedEvents.erase(it, timedEvents.end()); 

} 

Trả lời

40

erase() trả về một iterator mới:

for(iterator it = begin; it != end(container) /* !!! */;) 
{ 
    if (it->somecondition()) 
    { 
     it = vec.erase(it); // Returns the new iterator to continue from. 
    } 
    else 
    { 
     ++it; 
    } 
} 

Lưu ý rằng chúng tôi không còn có thể so sánh nó với một kết thúc precalculated, bởi vì chúng tôi có thể xóa nó và do đó làm mất hiệu lực nó. Chúng ta phải kết thúc một cách rõ ràng mỗi lần.

Phương pháp tốt hơn có thể là kết hợp std::remove_iferase(). Bạn thay đổi từ O (N) (mọi phần tử bị xoá hoàn toàn và chuyển khi bạn đi) để O (N):

iterator it = std::remove_if(begin, end, pred); 
vec.erase(it, vec.end()); 

đâu pred là vị loại bỏ của bạn, chẳng hạn như:

struct predicate // do choose a better name 
{ 
    bool operator()(const T& pX) const // replace T with your type 
    { 
     return pX.shouldIBeRemoved(); 
    } 
}; 

iterator it = std::remove_if(begin, end, predicate()); 
vec.erase(it, vec.end()); 

trong trường hợp của bạn, bạn có thể làm cho nó khá chung: tồn tại

class remove_by_caller 
{ 
public: 
    remove_by_caller(AguiWidgetBase* pWidget) : 
    mWidget(pWidget) 
    {} 

    // if every thing that has getCaller has a base, use that instead 
    template <typename T> // for now a template 
    bool operator()(const T& pX) const 
    { 
     return pX.getCaller() == mWidget; 
    } 

private: 
    AguiWidgetBase* mWidget; 
}; 

std::vector<AguiTimedEvent>::iterator it = 
    std::remove_if(timedEvents.begin(), timedEvents.end(), remove_by_caller(widget)); 
timedEvents.erase(it, timedEvents.end()); 

Note lambda để đơn giản hóa quá trình này, cả về Boost và C++ 11.

+0

Xin cảm ơn! +1 :) – jmasterx

+0

Tôi không chắc mình hiểu phương thức đầu tiên là N bình phương, tại sao nó không phải N, tôi chỉ lặp lại một lần để loại bỏ các mục. – jmasterx

+0

Trừ khi ofcourse các iterator trở lại bằng cách xóa mang lại cho bạn trở lại đầu trang – jmasterx

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