how can I delete every second element from std::list in cpp? [closed]
I'm trying to delete every second element from std::list but I'm getting segment error (core dump) when I run erase().
#include <bits/stdc++.h>
using namespace std;
int main()
{
list <int> num_list;
list <int> :: iterator it;
num_list.push_back(1);
num_list.push_back(2);
num_list.push_back(3);
num_list.push_back(4);
num_list.push_back(5);
cout << num_list.size() << endl;
it = num_list.begin();
advance(it, 1);
for(it; it != num_list.end(); advance(it, 2)) {
num_list.erase(it);
}
for(it = num_list.begin(); it != num_list.end(); ++it) {
cout << *it << " ";
}
cout << endl;
return 0;
}
c++
closed as off-topic by Peter Ruderman, gsamaras, SergeyA, Neil Butterworth, dandan78 Nov 14 '18 at 8:18
This question appears to be off-topic. The users who voted to close gave this specific reason:
- "This question was caused by a problem that can no longer be reproduced or a simple typographical error. While similar questions may be on-topic here, this one was resolved in a manner unlikely to help future readers. This can often be avoided by identifying and closely inspecting the shortest program necessary to reproduce the problem before posting." – Peter Ruderman, gsamaras, SergeyA, dandan78
If this question can be reworded to fit the rules in the help center, please edit the question.
|
show 7 more comments
I'm trying to delete every second element from std::list but I'm getting segment error (core dump) when I run erase().
#include <bits/stdc++.h>
using namespace std;
int main()
{
list <int> num_list;
list <int> :: iterator it;
num_list.push_back(1);
num_list.push_back(2);
num_list.push_back(3);
num_list.push_back(4);
num_list.push_back(5);
cout << num_list.size() << endl;
it = num_list.begin();
advance(it, 1);
for(it; it != num_list.end(); advance(it, 2)) {
num_list.erase(it);
}
for(it = num_list.begin(); it != num_list.end(); ++it) {
cout << *it << " ";
}
cout << endl;
return 0;
}
c++
closed as off-topic by Peter Ruderman, gsamaras, SergeyA, Neil Butterworth, dandan78 Nov 14 '18 at 8:18
This question appears to be off-topic. The users who voted to close gave this specific reason:
- "This question was caused by a problem that can no longer be reproduced or a simple typographical error. While similar questions may be on-topic here, this one was resolved in a manner unlikely to help future readers. This can often be avoided by identifying and closely inspecting the shortest program necessary to reproduce the problem before posting." – Peter Ruderman, gsamaras, SergeyA, dandan78
If this question can be reworded to fit the rules in the help center, please edit the question.
4
where do you initializeit
?
– Stephan Lechner
Nov 13 '18 at 16:31
1
Youradvance(it, 2)
call will run past the end of the list if it has an even number of elements. Your erase call also invalidatesit
, so advancing it afterwards is undefined behaviour.
– Peter Ruderman
Nov 13 '18 at 16:36
4
Unrelated:#include <bits/stdc++.h>
should not be used (Why).using namespace std;
should be avoided (Why). Together they amplify some of the other's worst effects and can result in some very odd errors.
– user4581301
Nov 13 '18 at 16:37
3
Why should this be closed? Deleting alternating elements is a non-trivial task (due to iterator invalidation). Somewhat surprisingly, it does not appear to be asked before. The code (now fixed) is pretty minimal and causes the error claimed, while the intent is also clear.
– MSalters
Nov 13 '18 at 16:51
2
@PeterRuderman: usually you'd do that withstd::remove_if
. That won't work here, though. So another reason why this isn't such a bad question.
– MSalters
Nov 13 '18 at 16:57
|
show 7 more comments
I'm trying to delete every second element from std::list but I'm getting segment error (core dump) when I run erase().
#include <bits/stdc++.h>
using namespace std;
int main()
{
list <int> num_list;
list <int> :: iterator it;
num_list.push_back(1);
num_list.push_back(2);
num_list.push_back(3);
num_list.push_back(4);
num_list.push_back(5);
cout << num_list.size() << endl;
it = num_list.begin();
advance(it, 1);
for(it; it != num_list.end(); advance(it, 2)) {
num_list.erase(it);
}
for(it = num_list.begin(); it != num_list.end(); ++it) {
cout << *it << " ";
}
cout << endl;
return 0;
}
c++
I'm trying to delete every second element from std::list but I'm getting segment error (core dump) when I run erase().
#include <bits/stdc++.h>
using namespace std;
int main()
{
list <int> num_list;
list <int> :: iterator it;
num_list.push_back(1);
num_list.push_back(2);
num_list.push_back(3);
num_list.push_back(4);
num_list.push_back(5);
cout << num_list.size() << endl;
it = num_list.begin();
advance(it, 1);
for(it; it != num_list.end(); advance(it, 2)) {
num_list.erase(it);
}
for(it = num_list.begin(); it != num_list.end(); ++it) {
cout << *it << " ";
}
cout << endl;
return 0;
}
c++
c++
edited Nov 13 '18 at 16:35
Shaman Sharif Asif
asked Nov 13 '18 at 16:28
Shaman Sharif AsifShaman Sharif Asif
273
273
closed as off-topic by Peter Ruderman, gsamaras, SergeyA, Neil Butterworth, dandan78 Nov 14 '18 at 8:18
This question appears to be off-topic. The users who voted to close gave this specific reason:
- "This question was caused by a problem that can no longer be reproduced or a simple typographical error. While similar questions may be on-topic here, this one was resolved in a manner unlikely to help future readers. This can often be avoided by identifying and closely inspecting the shortest program necessary to reproduce the problem before posting." – Peter Ruderman, gsamaras, SergeyA, dandan78
If this question can be reworded to fit the rules in the help center, please edit the question.
closed as off-topic by Peter Ruderman, gsamaras, SergeyA, Neil Butterworth, dandan78 Nov 14 '18 at 8:18
This question appears to be off-topic. The users who voted to close gave this specific reason:
- "This question was caused by a problem that can no longer be reproduced or a simple typographical error. While similar questions may be on-topic here, this one was resolved in a manner unlikely to help future readers. This can often be avoided by identifying and closely inspecting the shortest program necessary to reproduce the problem before posting." – Peter Ruderman, gsamaras, SergeyA, dandan78
If this question can be reworded to fit the rules in the help center, please edit the question.
4
where do you initializeit
?
– Stephan Lechner
Nov 13 '18 at 16:31
1
Youradvance(it, 2)
call will run past the end of the list if it has an even number of elements. Your erase call also invalidatesit
, so advancing it afterwards is undefined behaviour.
– Peter Ruderman
Nov 13 '18 at 16:36
4
Unrelated:#include <bits/stdc++.h>
should not be used (Why).using namespace std;
should be avoided (Why). Together they amplify some of the other's worst effects and can result in some very odd errors.
– user4581301
Nov 13 '18 at 16:37
3
Why should this be closed? Deleting alternating elements is a non-trivial task (due to iterator invalidation). Somewhat surprisingly, it does not appear to be asked before. The code (now fixed) is pretty minimal and causes the error claimed, while the intent is also clear.
– MSalters
Nov 13 '18 at 16:51
2
@PeterRuderman: usually you'd do that withstd::remove_if
. That won't work here, though. So another reason why this isn't such a bad question.
– MSalters
Nov 13 '18 at 16:57
|
show 7 more comments
4
where do you initializeit
?
– Stephan Lechner
Nov 13 '18 at 16:31
1
Youradvance(it, 2)
call will run past the end of the list if it has an even number of elements. Your erase call also invalidatesit
, so advancing it afterwards is undefined behaviour.
– Peter Ruderman
Nov 13 '18 at 16:36
4
Unrelated:#include <bits/stdc++.h>
should not be used (Why).using namespace std;
should be avoided (Why). Together they amplify some of the other's worst effects and can result in some very odd errors.
– user4581301
Nov 13 '18 at 16:37
3
Why should this be closed? Deleting alternating elements is a non-trivial task (due to iterator invalidation). Somewhat surprisingly, it does not appear to be asked before. The code (now fixed) is pretty minimal and causes the error claimed, while the intent is also clear.
– MSalters
Nov 13 '18 at 16:51
2
@PeterRuderman: usually you'd do that withstd::remove_if
. That won't work here, though. So another reason why this isn't such a bad question.
– MSalters
Nov 13 '18 at 16:57
4
4
where do you initialize
it
?– Stephan Lechner
Nov 13 '18 at 16:31
where do you initialize
it
?– Stephan Lechner
Nov 13 '18 at 16:31
1
1
Your
advance(it, 2)
call will run past the end of the list if it has an even number of elements. Your erase call also invalidates it
, so advancing it afterwards is undefined behaviour.– Peter Ruderman
Nov 13 '18 at 16:36
Your
advance(it, 2)
call will run past the end of the list if it has an even number of elements. Your erase call also invalidates it
, so advancing it afterwards is undefined behaviour.– Peter Ruderman
Nov 13 '18 at 16:36
4
4
Unrelated:
#include <bits/stdc++.h>
should not be used (Why). using namespace std;
should be avoided (Why). Together they amplify some of the other's worst effects and can result in some very odd errors.– user4581301
Nov 13 '18 at 16:37
Unrelated:
#include <bits/stdc++.h>
should not be used (Why). using namespace std;
should be avoided (Why). Together they amplify some of the other's worst effects and can result in some very odd errors.– user4581301
Nov 13 '18 at 16:37
3
3
Why should this be closed? Deleting alternating elements is a non-trivial task (due to iterator invalidation). Somewhat surprisingly, it does not appear to be asked before. The code (now fixed) is pretty minimal and causes the error claimed, while the intent is also clear.
– MSalters
Nov 13 '18 at 16:51
Why should this be closed? Deleting alternating elements is a non-trivial task (due to iterator invalidation). Somewhat surprisingly, it does not appear to be asked before. The code (now fixed) is pretty minimal and causes the error claimed, while the intent is also clear.
– MSalters
Nov 13 '18 at 16:51
2
2
@PeterRuderman: usually you'd do that with
std::remove_if
. That won't work here, though. So another reason why this isn't such a bad question.– MSalters
Nov 13 '18 at 16:57
@PeterRuderman: usually you'd do that with
std::remove_if
. That won't work here, though. So another reason why this isn't such a bad question.– MSalters
Nov 13 '18 at 16:57
|
show 7 more comments
3 Answers
3
active
oldest
votes
Start from the second item: next(num_list.begin(), 1)
. The erase
method returns an iterator to the next item of the removed item. So you can use just ++
operator to step 2.
int main()
{
list<int> num_list;
num_list.push_back(1);
num_list.push_back(2);
num_list.push_back(3);
num_list.push_back(4);
num_list.push_back(5);
cout << num_list.size() << endl;
for (auto it = next(num_list.begin(), 1); it != num_list.end();) {
it = num_list.erase(it);
if (it != num_list.end())
++it;
}
for (auto it = num_list.begin(); it != num_list.end(); ++it) {
cout << *it << " ";
}
cout << endl;
return 0;
}
add a comment |
For a good explanation on why your approach does not work, see Stepan Lechner's answer.
A completely different approach using std::remove_if
and lambda expressions:
int main() {
std::list<int> ints{1, 2, 3, 4, 5};
auto position = std::remove_if(ints.begin(), ints.end(),
[counter = 0](const auto x) mutable {
return ++counter % 2 == 0;
});
ints.erase(position, ints.end());
for(const auto x : ints) {
std::cout << x << ' ';
}
}
std::remove_if
, paired with erase
methods calls, is the algorithm for removing particular elements from a range. Here, it gets a little tricky - we want to remove every second element, so we need a predicate, which will return true
only for the even positions in the list. We achieve it using a member counter initialized with lambda init capture.
EDIT: As correctly stated by MSalters in the comments, using std::list::remove_if
is a superior solution to erase-remove
idiom from <algorithm>
. It takes advantage of internal std::list
implementation, plus it's simply less awkward to type:
// *ints* being the list itself
ints.remove_if([counter = 0](const auto x) mutable {
return ++counter % 2 == 0;
});
as opposed to the original:
auto position = std::remove_if(ints.begin(), ints.end(),
[counter = 0](const auto x) mutable {
return ++counter % 2 == 0;
});
ints.erase(position, ints.end());
3
There's astd::list::remove_if
which does not require the.erase
.
– MSalters
Nov 13 '18 at 17:17
@MSalters that is indeed the superior solution. I have added that to my answer
– Fureeish
Nov 13 '18 at 17:24
add a comment |
Erasing an element of a list invalidates the respective iterator, such that it must not be used for dereferencing or advancing
any more. Iterators pointing to other elements than the erased one, however, are not affected.
So you just need to remember an iterator position to be deleted and advance the original iterator before erasing the "toDelete"-position:
int main()
{
list <int> num_list;
num_list.push_back(1);
num_list.push_back(2);
num_list.push_back(3);
num_list.push_back(4);
num_list.push_back(5);
size_t size = num_list.size();
cout << size << endl;
list <int> :: iterator it = num_list.begin();
while(size--) {
auto toDelete = it;
it++;
if (size%2==1)
num_list.erase(toDelete);
}
for(it = num_list.begin(); it != num_list.end(); ++it) {
cout << *it << " ";
}
cout << endl;
return 0;
}
1
A bit overkill to keep two state variables (size
andit
) but it works.
– MSalters
Nov 13 '18 at 16:55
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Start from the second item: next(num_list.begin(), 1)
. The erase
method returns an iterator to the next item of the removed item. So you can use just ++
operator to step 2.
int main()
{
list<int> num_list;
num_list.push_back(1);
num_list.push_back(2);
num_list.push_back(3);
num_list.push_back(4);
num_list.push_back(5);
cout << num_list.size() << endl;
for (auto it = next(num_list.begin(), 1); it != num_list.end();) {
it = num_list.erase(it);
if (it != num_list.end())
++it;
}
for (auto it = num_list.begin(); it != num_list.end(); ++it) {
cout << *it << " ";
}
cout << endl;
return 0;
}
add a comment |
Start from the second item: next(num_list.begin(), 1)
. The erase
method returns an iterator to the next item of the removed item. So you can use just ++
operator to step 2.
int main()
{
list<int> num_list;
num_list.push_back(1);
num_list.push_back(2);
num_list.push_back(3);
num_list.push_back(4);
num_list.push_back(5);
cout << num_list.size() << endl;
for (auto it = next(num_list.begin(), 1); it != num_list.end();) {
it = num_list.erase(it);
if (it != num_list.end())
++it;
}
for (auto it = num_list.begin(); it != num_list.end(); ++it) {
cout << *it << " ";
}
cout << endl;
return 0;
}
add a comment |
Start from the second item: next(num_list.begin(), 1)
. The erase
method returns an iterator to the next item of the removed item. So you can use just ++
operator to step 2.
int main()
{
list<int> num_list;
num_list.push_back(1);
num_list.push_back(2);
num_list.push_back(3);
num_list.push_back(4);
num_list.push_back(5);
cout << num_list.size() << endl;
for (auto it = next(num_list.begin(), 1); it != num_list.end();) {
it = num_list.erase(it);
if (it != num_list.end())
++it;
}
for (auto it = num_list.begin(); it != num_list.end(); ++it) {
cout << *it << " ";
}
cout << endl;
return 0;
}
Start from the second item: next(num_list.begin(), 1)
. The erase
method returns an iterator to the next item of the removed item. So you can use just ++
operator to step 2.
int main()
{
list<int> num_list;
num_list.push_back(1);
num_list.push_back(2);
num_list.push_back(3);
num_list.push_back(4);
num_list.push_back(5);
cout << num_list.size() << endl;
for (auto it = next(num_list.begin(), 1); it != num_list.end();) {
it = num_list.erase(it);
if (it != num_list.end())
++it;
}
for (auto it = num_list.begin(); it != num_list.end(); ++it) {
cout << *it << " ";
}
cout << endl;
return 0;
}
edited Nov 13 '18 at 16:59
answered Nov 13 '18 at 16:53
PeterPeter
62618
62618
add a comment |
add a comment |
For a good explanation on why your approach does not work, see Stepan Lechner's answer.
A completely different approach using std::remove_if
and lambda expressions:
int main() {
std::list<int> ints{1, 2, 3, 4, 5};
auto position = std::remove_if(ints.begin(), ints.end(),
[counter = 0](const auto x) mutable {
return ++counter % 2 == 0;
});
ints.erase(position, ints.end());
for(const auto x : ints) {
std::cout << x << ' ';
}
}
std::remove_if
, paired with erase
methods calls, is the algorithm for removing particular elements from a range. Here, it gets a little tricky - we want to remove every second element, so we need a predicate, which will return true
only for the even positions in the list. We achieve it using a member counter initialized with lambda init capture.
EDIT: As correctly stated by MSalters in the comments, using std::list::remove_if
is a superior solution to erase-remove
idiom from <algorithm>
. It takes advantage of internal std::list
implementation, plus it's simply less awkward to type:
// *ints* being the list itself
ints.remove_if([counter = 0](const auto x) mutable {
return ++counter % 2 == 0;
});
as opposed to the original:
auto position = std::remove_if(ints.begin(), ints.end(),
[counter = 0](const auto x) mutable {
return ++counter % 2 == 0;
});
ints.erase(position, ints.end());
3
There's astd::list::remove_if
which does not require the.erase
.
– MSalters
Nov 13 '18 at 17:17
@MSalters that is indeed the superior solution. I have added that to my answer
– Fureeish
Nov 13 '18 at 17:24
add a comment |
For a good explanation on why your approach does not work, see Stepan Lechner's answer.
A completely different approach using std::remove_if
and lambda expressions:
int main() {
std::list<int> ints{1, 2, 3, 4, 5};
auto position = std::remove_if(ints.begin(), ints.end(),
[counter = 0](const auto x) mutable {
return ++counter % 2 == 0;
});
ints.erase(position, ints.end());
for(const auto x : ints) {
std::cout << x << ' ';
}
}
std::remove_if
, paired with erase
methods calls, is the algorithm for removing particular elements from a range. Here, it gets a little tricky - we want to remove every second element, so we need a predicate, which will return true
only for the even positions in the list. We achieve it using a member counter initialized with lambda init capture.
EDIT: As correctly stated by MSalters in the comments, using std::list::remove_if
is a superior solution to erase-remove
idiom from <algorithm>
. It takes advantage of internal std::list
implementation, plus it's simply less awkward to type:
// *ints* being the list itself
ints.remove_if([counter = 0](const auto x) mutable {
return ++counter % 2 == 0;
});
as opposed to the original:
auto position = std::remove_if(ints.begin(), ints.end(),
[counter = 0](const auto x) mutable {
return ++counter % 2 == 0;
});
ints.erase(position, ints.end());
3
There's astd::list::remove_if
which does not require the.erase
.
– MSalters
Nov 13 '18 at 17:17
@MSalters that is indeed the superior solution. I have added that to my answer
– Fureeish
Nov 13 '18 at 17:24
add a comment |
For a good explanation on why your approach does not work, see Stepan Lechner's answer.
A completely different approach using std::remove_if
and lambda expressions:
int main() {
std::list<int> ints{1, 2, 3, 4, 5};
auto position = std::remove_if(ints.begin(), ints.end(),
[counter = 0](const auto x) mutable {
return ++counter % 2 == 0;
});
ints.erase(position, ints.end());
for(const auto x : ints) {
std::cout << x << ' ';
}
}
std::remove_if
, paired with erase
methods calls, is the algorithm for removing particular elements from a range. Here, it gets a little tricky - we want to remove every second element, so we need a predicate, which will return true
only for the even positions in the list. We achieve it using a member counter initialized with lambda init capture.
EDIT: As correctly stated by MSalters in the comments, using std::list::remove_if
is a superior solution to erase-remove
idiom from <algorithm>
. It takes advantage of internal std::list
implementation, plus it's simply less awkward to type:
// *ints* being the list itself
ints.remove_if([counter = 0](const auto x) mutable {
return ++counter % 2 == 0;
});
as opposed to the original:
auto position = std::remove_if(ints.begin(), ints.end(),
[counter = 0](const auto x) mutable {
return ++counter % 2 == 0;
});
ints.erase(position, ints.end());
For a good explanation on why your approach does not work, see Stepan Lechner's answer.
A completely different approach using std::remove_if
and lambda expressions:
int main() {
std::list<int> ints{1, 2, 3, 4, 5};
auto position = std::remove_if(ints.begin(), ints.end(),
[counter = 0](const auto x) mutable {
return ++counter % 2 == 0;
});
ints.erase(position, ints.end());
for(const auto x : ints) {
std::cout << x << ' ';
}
}
std::remove_if
, paired with erase
methods calls, is the algorithm for removing particular elements from a range. Here, it gets a little tricky - we want to remove every second element, so we need a predicate, which will return true
only for the even positions in the list. We achieve it using a member counter initialized with lambda init capture.
EDIT: As correctly stated by MSalters in the comments, using std::list::remove_if
is a superior solution to erase-remove
idiom from <algorithm>
. It takes advantage of internal std::list
implementation, plus it's simply less awkward to type:
// *ints* being the list itself
ints.remove_if([counter = 0](const auto x) mutable {
return ++counter % 2 == 0;
});
as opposed to the original:
auto position = std::remove_if(ints.begin(), ints.end(),
[counter = 0](const auto x) mutable {
return ++counter % 2 == 0;
});
ints.erase(position, ints.end());
edited Nov 13 '18 at 17:34
answered Nov 13 '18 at 17:06
FureeishFureeish
3,28321029
3,28321029
3
There's astd::list::remove_if
which does not require the.erase
.
– MSalters
Nov 13 '18 at 17:17
@MSalters that is indeed the superior solution. I have added that to my answer
– Fureeish
Nov 13 '18 at 17:24
add a comment |
3
There's astd::list::remove_if
which does not require the.erase
.
– MSalters
Nov 13 '18 at 17:17
@MSalters that is indeed the superior solution. I have added that to my answer
– Fureeish
Nov 13 '18 at 17:24
3
3
There's a
std::list::remove_if
which does not require the .erase
.– MSalters
Nov 13 '18 at 17:17
There's a
std::list::remove_if
which does not require the .erase
.– MSalters
Nov 13 '18 at 17:17
@MSalters that is indeed the superior solution. I have added that to my answer
– Fureeish
Nov 13 '18 at 17:24
@MSalters that is indeed the superior solution. I have added that to my answer
– Fureeish
Nov 13 '18 at 17:24
add a comment |
Erasing an element of a list invalidates the respective iterator, such that it must not be used for dereferencing or advancing
any more. Iterators pointing to other elements than the erased one, however, are not affected.
So you just need to remember an iterator position to be deleted and advance the original iterator before erasing the "toDelete"-position:
int main()
{
list <int> num_list;
num_list.push_back(1);
num_list.push_back(2);
num_list.push_back(3);
num_list.push_back(4);
num_list.push_back(5);
size_t size = num_list.size();
cout << size << endl;
list <int> :: iterator it = num_list.begin();
while(size--) {
auto toDelete = it;
it++;
if (size%2==1)
num_list.erase(toDelete);
}
for(it = num_list.begin(); it != num_list.end(); ++it) {
cout << *it << " ";
}
cout << endl;
return 0;
}
1
A bit overkill to keep two state variables (size
andit
) but it works.
– MSalters
Nov 13 '18 at 16:55
add a comment |
Erasing an element of a list invalidates the respective iterator, such that it must not be used for dereferencing or advancing
any more. Iterators pointing to other elements than the erased one, however, are not affected.
So you just need to remember an iterator position to be deleted and advance the original iterator before erasing the "toDelete"-position:
int main()
{
list <int> num_list;
num_list.push_back(1);
num_list.push_back(2);
num_list.push_back(3);
num_list.push_back(4);
num_list.push_back(5);
size_t size = num_list.size();
cout << size << endl;
list <int> :: iterator it = num_list.begin();
while(size--) {
auto toDelete = it;
it++;
if (size%2==1)
num_list.erase(toDelete);
}
for(it = num_list.begin(); it != num_list.end(); ++it) {
cout << *it << " ";
}
cout << endl;
return 0;
}
1
A bit overkill to keep two state variables (size
andit
) but it works.
– MSalters
Nov 13 '18 at 16:55
add a comment |
Erasing an element of a list invalidates the respective iterator, such that it must not be used for dereferencing or advancing
any more. Iterators pointing to other elements than the erased one, however, are not affected.
So you just need to remember an iterator position to be deleted and advance the original iterator before erasing the "toDelete"-position:
int main()
{
list <int> num_list;
num_list.push_back(1);
num_list.push_back(2);
num_list.push_back(3);
num_list.push_back(4);
num_list.push_back(5);
size_t size = num_list.size();
cout << size << endl;
list <int> :: iterator it = num_list.begin();
while(size--) {
auto toDelete = it;
it++;
if (size%2==1)
num_list.erase(toDelete);
}
for(it = num_list.begin(); it != num_list.end(); ++it) {
cout << *it << " ";
}
cout << endl;
return 0;
}
Erasing an element of a list invalidates the respective iterator, such that it must not be used for dereferencing or advancing
any more. Iterators pointing to other elements than the erased one, however, are not affected.
So you just need to remember an iterator position to be deleted and advance the original iterator before erasing the "toDelete"-position:
int main()
{
list <int> num_list;
num_list.push_back(1);
num_list.push_back(2);
num_list.push_back(3);
num_list.push_back(4);
num_list.push_back(5);
size_t size = num_list.size();
cout << size << endl;
list <int> :: iterator it = num_list.begin();
while(size--) {
auto toDelete = it;
it++;
if (size%2==1)
num_list.erase(toDelete);
}
for(it = num_list.begin(); it != num_list.end(); ++it) {
cout << *it << " ";
}
cout << endl;
return 0;
}
answered Nov 13 '18 at 16:49
Stephan LechnerStephan Lechner
28.4k32143
28.4k32143
1
A bit overkill to keep two state variables (size
andit
) but it works.
– MSalters
Nov 13 '18 at 16:55
add a comment |
1
A bit overkill to keep two state variables (size
andit
) but it works.
– MSalters
Nov 13 '18 at 16:55
1
1
A bit overkill to keep two state variables (
size
and it
) but it works.– MSalters
Nov 13 '18 at 16:55
A bit overkill to keep two state variables (
size
and it
) but it works.– MSalters
Nov 13 '18 at 16:55
add a comment |
4
where do you initialize
it
?– Stephan Lechner
Nov 13 '18 at 16:31
1
Your
advance(it, 2)
call will run past the end of the list if it has an even number of elements. Your erase call also invalidatesit
, so advancing it afterwards is undefined behaviour.– Peter Ruderman
Nov 13 '18 at 16:36
4
Unrelated:
#include <bits/stdc++.h>
should not be used (Why).using namespace std;
should be avoided (Why). Together they amplify some of the other's worst effects and can result in some very odd errors.– user4581301
Nov 13 '18 at 16:37
3
Why should this be closed? Deleting alternating elements is a non-trivial task (due to iterator invalidation). Somewhat surprisingly, it does not appear to be asked before. The code (now fixed) is pretty minimal and causes the error claimed, while the intent is also clear.
– MSalters
Nov 13 '18 at 16:51
2
@PeterRuderman: usually you'd do that with
std::remove_if
. That won't work here, though. So another reason why this isn't such a bad question.– MSalters
Nov 13 '18 at 16:57