populate c++ maps content in a loop scope – Education Career Blog

I try to populate the content of a c++ map within a loop scope.

#include <set>
#include <map>

map<int, set<int> > maps;

for (int i=0; i<10; i++) {
   set<int> seti;    // content: a set of integers
   seti.insert(i);
   seti.insert(...);
   maps.insert ( pair<int,set<int> >(i,seti) );
}

The question is:
does maps.insert copy the pair content?
If the pair instance is invalid after each loop scope, then such code should fail.

How should I properly generate map content (with pointer and new the instance?) and how to clean up a map properly?

thanks for any suggestion for best practices.

— UPDATE —

map<int, set<int> >::iterator it;
int k      = (*it).first;     
set<int> v = (*it).second;       

is now the ‘v’ also a copied one from the real instance stored in map?
if yes, than I have no way to ‘directly’ update the map content.

,

You do not have to explicitly create the set object, as it will be created in the map when you access it with the operator. Hence, you can simply write

#include <set>
#include <map>

map<int, set<int> > maps;

for (int i=0; i<10; i++) {
   mapsi.insert(i);
}

,

Yes, it copies the content. So a new copy of the set gets inserted at each iteration of the for loop. If that is what you want, you can do it more succinctly using the make_pair function:

#include <set> 
#include <map> 

map<int, set<int> > maps; 

for (int i=0; i<10; i++) { 
   set<int> seti;    // content 
   seti.insert(i); 
   maps.insert ( std::make_pair(i,seti) ); 
} 

It is not clear to me why you want a set with only a single element, unless you plan to add elements to it in the future.

UPDATED:
In answer to your update. As long as the value in your map is a container of a basic value type, any updates you make to it will not affect the original value you inserted into the map.

,

The code you have posted should work just fine. Because of regular type semantics the values will be copied where they belong. The map (and all instances of the regular types the map contains) will destruct properly when they fall out of scope.

,

I have to admit that the variable name maps in the following line confused me

map<int, set<int> > maps;

It conveyed a notion that there are many maps, whereas in reality, there is only one.

Two loops are required:

  • one to construct a set of int‘s, and
  • a second one to insert those sets into the map.

Here is a code sample

typedef std::set< int > IntSet;
typedef std::map< int, IntSet > MapOfIntSet;

MapOfIntSet myMap;     // container

for( int i = 0; i < N; ++i ) {
    IntSet intSet;
    for( int j = i + 1; j < N; ++j ) {
        intSet.insert( j );
    }

    // Both the following line does the same, any one can be used
    // myMap.insert( make_pair( i, intSet ) );
    myMap i  = intSet;
}

A complete program with output is uploaded at codepad.

,

Yes, the whole set is copied inside, which is a performance bottleneck. I don’t like the solutions proposed because of this. And also, as you ask using pointers, you can do this one safely using boost::shared_ptr. The code could look like this:

#include <set>
#include <map>
#include <boost/shared_ptr.hpp>

// I add typedefs for clarity
typedef boost::shared_ptr< set<int> > set_ptr;

using namespace std;

map<int, set_ptr > maps;

for (int i=0; i<10; i++) {
   set_ptr seti( new set<int>());    // content
   seti->insert(i);
   maps.insert ( std::make_pair(i,seti) );
}

Note that now you’re only copying safe pointers, that get deleted when maps gets deleted.

Leave a Comment