[英]Vector erase iterator
我有這個代碼:
int main()
{
vector<int> res;
res.push_back(1);
vector<int>::iterator it = res.begin();
for( ; it != res.end(); it++)
{
it = res.erase(it);
//if(it == res.end())
// return 0;
}
}
“一個隨機訪問迭代器,指向函數調用擦除的最后一個元素之后的元素的新位置,如果操作擦除了序列中的最后一個元素,則該位置是向量結束。”
這段代碼崩潰了,但如果我使用if(it == res.end())
部分然后返回,它就可以工作。 怎么來的? for 循環是否緩存res.end()
所以不等於運算符失敗?
res.erase(it)
總是返回下一個有效的迭代器,如果你擦除最后一個元素,它將指向.end()
在循環結束時++it
總是被調用,所以你增加了.end()
這是不允許的。
簡單地檢查.end()
仍然會留下一個錯誤,因為你總是在每次迭代時跳過一個元素( it
通過.erase()
的返回“遞增”,然后再次通過循環)
你可能想要這樣的東西:
while (it != res.end()) {
it = res.erase(it);
}
擦除每個元素
(為了完整性:我假設這是一個簡化的例子,如果你只是想讓每個元素都消失而不必對其執行操作(例如刪除),你應該簡單地調用res.clear()
)
當您僅有條件地擦除元素時,您可能需要類似
for ( ; it != res.end(); ) {
if (condition) {
it = res.erase(it);
} else {
++it;
}
}
for( ; it != res.end();)
{
it = res.erase(it);
}
或者,更一般的:
for( ; it != res.end();)
{
if (smth)
it = res.erase(it);
else
++it;
}
因為 vector 中的方法 erase 返回傳遞的迭代器的下一個迭代器。
我將舉例說明如何在迭代時刪除向量中的元素。
void test_del_vector(){
std::vector<int> vecInt{0, 1, 2, 3, 4, 5};
//method 1
for(auto it = vecInt.begin();it != vecInt.end();){
if(*it % 2){// remove all the odds
it = vecInt.erase(it); // note it will = next(it) after erase
} else{
++it;
}
}
// output all the remaining elements
for(auto const& it:vecInt)std::cout<<it;
std::cout<<std::endl;
// recreate vecInt, and use method 2
vecInt = {0, 1, 2, 3, 4, 5};
//method 2
for(auto it=std::begin(vecInt);it!=std::end(vecInt);){
if (*it % 2){
it = vecInt.erase(it);
}else{
++it;
}
}
// output all the remaining elements
for(auto const& it:vecInt)std::cout<<it;
std::cout<<std::endl;
// recreate vecInt, and use method 3
vecInt = {0, 1, 2, 3, 4, 5};
//method 3
vecInt.erase(std::remove_if(vecInt.begin(), vecInt.end(),
[](const int a){return a % 2;}),
vecInt.end());
// output all the remaining elements
for(auto const& it:vecInt)std::cout<<it;
std::cout<<std::endl;
}
輸出aw如下:
024
024
024
更多的生成方法:
template<class Container, class F>
void erase_where(Container& c, F&& f)
{
c.erase(std::remove_if(c.begin(), c.end(),std::forward<F>(f)),
c.end());
}
void test_del_vector(){
std::vector<int> vecInt{0, 1, 2, 3, 4, 5};
//method 4
auto is_odd = [](int x){return x % 2;};
erase_where(vecInt, is_odd);
// output all the remaining elements
for(auto const& it:vecInt)std::cout<<it;
std::cout<<std::endl;
}
it++ 指令在塊的末尾完成。 因此,如果您要擦除最后一個元素,則嘗試增加指向空集合的迭代器。
使用現代 C++ 可以做的事情是使用“std::remove_if”和 lambda 表達式;
此代碼將刪除向量的“3”
vector<int> vec {1,2,3,4,5,6};
vec.erase(std::remove_if(begin(vec),end(vec),[](int elem){return (elem == 3);}), end(vec));
不要擦除然后增加迭代器。 無需增加,如果您的向量具有奇數(或偶數,我不知道)元素數,您將錯過向量的末尾。
在 for 循環的循環表達式中將it
增加到(空)容器的末尾。
以下似乎也有效:
for (vector<int>::iterator it = res.begin(); it != res.end(); it++)
{
res.erase(it--);
}
不知道這有沒有什么漏洞?
if(allPlayers.empty() == false) {
for(int i = allPlayers.size() - 1; i >= 0; i--)
{
if(allPlayers.at(i).getpMoney() <= 0)
allPlayers.erase(allPlayers.at(i));
}
}
這對我有用。 並且不需要考慮索引已經擦除。
作為對 crazylammer 答案的修改,我經常使用:
your_vector_type::iterator it;
for( it = res.start(); it != res.end();)
{
your_vector_type::iterator curr = it++;
if (something)
res.erase(curr);
}
這樣做的好處是你不必擔心忘記增加迭代器,當你有復雜的邏輯時,它更不容易出錯。 在循環內部,curr 永遠不會等於 res.end(),並且無論您是否從向量中刪除它,它都將位於下一個元素。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.