벡터 지우기 반복기
이 코드가 있습니다.
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;
}
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 ()와 같지 않으며 벡터에서 지우더라도 다음 요소에 있습니다.
벡터의 지우기 메서드는 전달 된 이터레이터의 다음 이터레이터를 반환하기 때문입니다.
반복 할 때 벡터에서 요소를 제거하는 방법에 대한 예제를 제공합니다.
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;
}
output aw below:
024
024
024
A more generate method:
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;
}
Do not erase and then increment the iterator. No need to increment, if your vector has an odd (or even, I don't know) number of elements you will miss the end of the vector.
The it++ instruction is done at the end of the block. So if your are erasing the last element, then you try to increment the iterator that is pointing to an empty collection.
You increment it past the end of the (empty) container in the for loop's loop expression.
The following also seems to work :
for (vector<int>::iterator it = res.begin(); it != res.end(); it++)
{
res.erase(it--);
}
Not sure if there's any flaw in this ?
if(allPlayers.empty() == false) {
for(int i = allPlayers.size() - 1; i >= 0; i--)
{
if(allPlayers.at(i).getpMoney() <= 0)
allPlayers.erase(allPlayers.at(i));
}
}
This works for me. And Don't need to think about indexes have already erased.
참고URL : https://stackoverflow.com/questions/4645705/vector-erase-iterator
'Program Club' 카테고리의 다른 글
| Mac 터미널 Vim은 줄 끝에서만 백 스페이스를 사용합니다. (0) | 2020.11.19 |
|---|---|
| 중앙 양식 제출 버튼 HTML / CSS (0) | 2020.11.19 |
| Express에서 경로 일치를위한 정규식 (0) | 2020.11.19 |
| IntelliJ IDEA의 변경 목록은 무엇입니까? (0) | 2020.11.18 |
| transformClassesWithDexForDebug에서 Gradle 빌드가 느립니다. (0) | 2020.11.18 |