I want to know if the following check is necessary:
std::list<int> myList;
.....
for (std::list<int>::iterator itr = myList.begin(); itr != myList.end(); ++itr)
{
if (itr != NULL) // Is This Check Necessary?
{
// DO SOMTHING.
}
}
I have seen this check in some places and I'm wondering if that is a necessary check.
Maybe this check is necessary if the list is an input to a function?
Thanks,
Ofer.
No, it is an unnecessary check.
You might want to check *itr != nullptr, if the list held some kind of pointers.
No, it's not necessary. I am not sure it's even valid.
instead you can use new range based for loops (C++11), so you dont need to deal with iterator checking.
std::list<int> YourList;
for( auto z : YourList ) {
//
std::cout << z; // z is int
// amazing codes and fun :)
//
}
It's unnecessary to check.If the myList is empty,then myList.begin() equals to myList.end()
I think there's no way to test if an iterator is uninitialized,
But you can initialize iterator to the end() of the container as a default value.
std::list<int>::iterator itr = yourlist.end();
//
if (itr != yourlist.end())
{
//doSomething
}
Related
is it possible?
like this:
while(itr!=list.end())
{
++itr; //is it ok?
}
instead of:
for(itr=list.begin();itr!=list.end();++itr)
I guess it's just a personal favor but I prefer while a little bit more. thanks
A for-loop of the flavor:
for(init-stmt; test-expression; alter-stmt)
{
// code
}
is equivalent to:
init-stmt;
while (test-expression)
{
//code
alter-stmt
}
Provided your init-stmt logic is identical in preamble to your while-loop as that of your for-loop, there is no issue to be concerned about. In your case, it would appear as this:
itr = list.begin();
while (itr != list.end())
{
// code
++itr;
}
Variable Lifetime
It is worth noting the lifetime of the variables declared in the init-stmt can make these different. For example:
for (auto itr = list.begin(); itr != list.end(); ++itr)
{
// code
}
The variable itr has no lifetime outside the loop. To have an equivalent while-loop entails using a scope-wrapping set of braces:
{
auto itr = list.begin()
while (itr != list.end())
{
// code
++itr;
}
}
Finally, as others have suggested, perhaps a ranged-for-loop construct may better suit your needs. If interested, you can read more about it here .
Assuming you have a itr=list.begin() before that while loop, it's fine.
My STL is a bit rusty, so forgive me for asking a possibly trivial question. Consider the following piece of code:
map<int,int> m;
...
for (auto itr = m.begin(); itr != m.end(); ++itr) {
if (itr->second == 0) {
m.erase(itr);
}
}
The question is: Is it safe to erase elements while looping over the map?
Yes, but not the way you do it. You're invalidating itr when you erase, then incrementing the invalid iterator.
auto itr = m.begin();
while (itr != m.end()) {
if (itr->first == 0) {
m.erase(itr++);
} else {
++itr;
}
}
I think that you shouldn't use removed iterator at all - in case of lists this causes serious problems, shouldn't be different for maps.
EDIT by Matthieu M: this code is well-formed in C++0x and allowed as an extension by MSVC.
map<int,int> m;
...
auto itr = m.begin();
while (itr != m.end())
{
if (itr->second == 0) {
itr = m.erase(itr);
}
else
{
itr++;
}
}
For the example given, It would actually be easier to use the erase overload that takes a key as an argument. This function erases all elements in the map with the given key (for a map, this is always either zero or one element)
map<int,int> m;
// ...
m.erase(0); // erase all elements with key equivalent to 0
I have a stl set of integers and I would like to iterate through all unique pairs of integer values, where by uniqueness I consider val1,val2 and val2,val1 to be the same and I should only see that combination once.
I have written this in python where I use the index of a list (clusters):
for i in range(len(clusters) - 1):
for j in range(i+1,len(clusters)):
#Do something with clusters[i],clusters[j])
but without an index I am not sure how I can achieve the same thing with a stl set and iterators. I tried out:
for (set<int>::iterator itr = myset.begin(); itr != myset.end()-1; ++itr) {
cout << *itr;
}
but this fails as an iterator doesn't have a - operator.
How can I achieve this, or must I use a different container?
How about something along the following lines:
for(set<int>::const_iterator iter1 = myset.begin(); iter1 != myset.end(); ++iter1) {
for(set<int>::const_iterator iter2 = iter1; ++iter2 != myset.end();) {
{
std::cout << *iter1 << " " << *iter2 << "\n";
}
}
This yields all N*(N-1)/2 unique pairs, where N is the number of integers in your set.
As an aside: use a const_iterator whenever you iterate over a container without modifying anything, it's good style and might have better performance.
EDIT: Modified the code to reflect the suggestion made by Steve Jessop.
You don't need to do end() - 1 since end() is an iterator that points after the last element in the container.
The corrected code is:
for (set<int>::iterator itr = myset.begin(); itr != myset.end(); ++itr) {
for (set<int>::iterator itr2 = itr + 1; itr2 != myset.end(); ++itr2) {
// Do whatever you want with itr and itr2
}
}
Put your data in a boost::bimap, then iterate it both ways, copying the results into a standard STL map which will enforce uniqueness.
I'm new to C++. I'd like to know how experienced coders do this.
what I have:
set<int> s;
s.insert(1);
s.insert(2);
s.insert(3);
s.insert(4);
s.insert(5);
for(set<int>::iterator itr = s.begin(); itr != s.end(); ++itr){
if (!(*itr % 2))
s.erase(itr);
}
and of course, it doesn't work. because itr is incremented after it is erased.
does it mean Itr has to point to the begin of the set everytime after i erase the element from the set?
for(set<int>::iterator itr = s.begin(); itr != s.end(); ){
if (!(*itr % 2))
s.erase(itr++);
else ++itr;
}
effective STL by Scott Myers
Erasing an element from std::set only invalidates iterators pointing to that element.
Get an iterator to the next element before erasing the target element.
You don't need to go back to the start. set::erase only invalidates iterators that refer to the item being erased, so you just need to copy the iterator and increment before erasing:
for(set<int>::iterator itr = s.begin(); itr != s.end();)
{
set<int>::iterator here = itr++;
if (!(*here % 2))
s.erase(here);
}
The best way is to use the combination of remove_if and erase
s.erase(remove_if(s.begin(), s.end(), evenOddFunctor), s.end())
This will be helpful
http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove
Also Refer to effective STL by scott meyers
Edit: Although my solution is wrong i am not deleting it. It might be a good learning for someone like me who does not about mutable/immutable iterators
I'm trying to figure out the best way to determine whether I'm in the last iteration of a loop over a map in order to do something like the following:
for (iter = someMap.begin(); iter != someMap.end(); ++iter) {
bool last_iteration;
// do something for all iterations
if (!last_iteration) {
// do something for all but the last iteration
}
}
There seem to be several ways of doing this: random access iterators, the distance function, etc. What's the canonical method?
Edit: no random access iterators for maps!
Canonical? I can't claim that, but I'd suggest
final_iter = someMap.end();
--final_iter;
if (iter != final_iter) ...
Edited to correct as suggested by KTC. (Thanks! Sometimes you go too quick and mess up on the simplest things...)
Since C++11, you can also use std::next()
for (auto iter = someMap.begin(); iter != someMap.end(); ++iter) {
// do something for all iterations
if (std::next(iter) != someMap.end()) {
// do something for all but the last iteration
}
}
Although the question was asked a while ago, I thought it would be worth sharing.
This seems like the simplest:
bool last_iteration = iter == (--someMap.end());
If you just want to use a ForwardIterator, this should work:
for ( i = c.begin(); i != c.end(); ) {
iterator cur = i++;
// do something, using cur
if ( i != c.end() ) {
// do something using cur for all but the last iteration
}
}
Modified Mark Ransom's so it actually work as intended.
finalIter = someMap.end();
--finalIter;
if (iter != final_iter)
Surprised no one mentioned it yet, but of course boost has something ;)
Boost.Next (and the equivalent Boost.Prior)
Your example would look like:
for (iter = someMap.begin(); iter != someMap.end(); ++iter) {
// do something for all iterations
if (boost::next(iter) != someMap.end()) {
// do something for all but the last iteration
}
}
The following code would be optimized by a compiler so that to be the best solution for this task by performance as well as by OOP rules:
if (&*it == &*someMap.rbegin()) {
//the last iteration
}
This is the best code by OOP rules because std::map has got a special member function rbegin for the code like:
final_iter = someMap.end();
--final_iter;
Why to work to find the EOF so that you dont give something to it.
Simply, exclude it;
for (iter = someMap.begin(); someMap.end() - 1; ++iter) {
//apply to all from begin to second last element
}
KISS (KEEP IT SIMPLY SIMPLE)
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <algorithm>
using namespace boost::lambda;
// call the function foo on each element but the last...
if( !someMap.empty() )
{
std::for_each( someMap.begin(), --someMap.end(), bind( &Foo, _1 ) );
}
Using std::for_each will ensure that the loop is tight and accurate... Note the introduction of the function foo() which takes a single argument (the type should match what is contained in someMap). This approach has the added addition of being 1 line. Of course, if Foo is really small, you can use a lambda function and get rid of the call to &Foo.
How about this, no one mentioning but...
for (iter = someMap.begin(); iter != someMap.end(); ++iter) {
// do something for all iterations
if (iter != --someMap.end()) {
// do something for all but the last iteration
}
}
this seems simple, mm...
For someone who likes C++11 range-based loop:
for (const auto& pair : someMap) {
if (&pair != &*someMap.rbegin()) ...
}
Notice only reference type works here, not auto pair
A simple, yet effective, approach:
size_t items_remaining = someMap.size();
for (iter = someMap.begin(); iter != someMap.end(); iter++) {
bool last_iteration = items_remaining-- == 1;
}
Full program:
#include <iostream>
#include <list>
void process(int ii)
{
std::cout << " " << ii;
}
int main(void)
{
std::list<int> ll;
ll.push_back(1);
ll.push_back(2);
ll.push_back(3);
ll.push_back(4);
ll.push_back(5);
ll.push_back(6);
std::list<int>::iterator iter = ll.begin();
if (iter != ll.end())
{
std::list<int>::iterator lastIter = iter;
++ iter;
while (iter != ll.end())
{
process(*lastIter);
lastIter = iter;
++ iter;
}
// todo: think if you need to process *lastIter
std::cout << " | last:";
process(*lastIter);
}
std::cout << std::endl;
return 0;
}
This program yields:
1 2 3 4 5 | last: 6
Here's my optimized take:
iter = someMap.begin();
do {
// Note that curr = iter++ may involve up to three copy operations
curr = iter;
// Do stuff with curr
if (++iter == someMap.end()) {
// Oh, this was the last iteration
break;
}
// Do more stuff with curr
} while (true);
You can just pull an element out of the map prior to iteration, then perform your "last iteration" work out of the loop and then put the element back into the map. This is horribly bad for asynchronous code, but considering how bad the rest of C++ is for concurrency, I don't think it'll be an issue. :-)