Thursday, 14 March 2013

A word of caution about the unmanaged C++ 'for each' and 'auto' keywords

Recently I had the following code:

 
std::map<CString, std::vector<CString>> mapIdToChildren;
for(std::map<CString,std::vector<CString>>::iterator it = mapIdToChildren.begin();it!=mapIdToChildren.end();++it)
 std::sort( (*it).second.begin(), (*it).second.end() );
 

And tried replacing it with the 'for each' keyword:
for eachauto it in mapIdToChildren )
 std::sort( it.second.begin(), it.second.end() );
 

But found that the result is unsorted..
What is really happening is that the 'auto' is expanded to the following which means the vector is copied, so the original object remains unsorted:
for each( std::pair<CString,std::vector<CString>> it in mapIdToChildren )
 std::sort( it.second.begin(), it.second.end() );
 

Unfortunately the following code doesn't compile..
for each( std::pair<CString,std::vector<CString>>& it in mapIdToChildren )
 std::sort( it.second.begin(), it.second.end() );
 

Another failure:
for each( std::map<CString,std::vector<CString>>::iterator it in mapIdToChildren )
 std::sort( (*it).second.begin(), (*it).second.end() );
 

In conclusion you should be careful when using the 'auto' keyword in conjunction with 'for each' because you may not be getting what you think.

No comments:

Post a Comment