tags:

views:

146

answers:

4

Basically I have,

typedef  map<std::string, set<double> > MAP_STRING_TO_SET;

What is the best way to update (add or remove value) the set with a new value without causing the set to be copied?

The only viable solution I see is to use map<std::string, set<double>* > -- something I don't want to do.

Thanks

A: 

I think you can just use swap - eg.

my_map["123"].swap(my_set)

provided clobbering my_set doesn't matter to you. This would swap the previous contents of my_map["123"] with my_set, and it's fast.

The indexing operator[] returns a reference to the contained set - therefore, you can manipulate it just like any other variable. If you want to add/remove individual values, you can just use insert() or erase() methods - eg. my_map["123"].insert(123).

The copying actually takes place when you assign a new set to the map - eg.

my_map["123"]=my_set

would create a copy of my_set. If you don't need to use the value of my_set later, you can use the swap() method, which will just shuffle pointers of the two sets. my_set will, however, have the contents of the previous my_map["123"].

jpalecek
elaborate please...
+4  A: 

The set is only copied in initialization. You are allowed to do something like

myMap[myString].insert(myDouble);

since map::operator[] returns a reference.

rlbond
are you sure? Wouldn't myMap[myString] create a temporary copy of the set, hence I will NOT actually update the set in the map?
No, it creates a reference. It is not a temporary copy. Maps would be quite useless otherwise.
rlbond
+1  A: 

Do you mean like:

MAP_STRING_TO_SET map;

/* insert some sets under the name "a","b", etc */

map["a"].erase(5.0); // <-

Because no maps are copied on the line marked with <-, as [] returns a reference.

Or do you mean:

MAP_STRING_TO_SET map;

/* insert some sets under the name "a","b", etc */

map["newset"].insert(5.0); // <=

Where you are inserting a new set? In this case I'm also sure the map stores pointers to sets internally, so if it does any moving of nodes at all, it will be fast.

But someone correct me if I'm mistaken.

GMan
A: 

You can also do this:

map<std::string, set<double> >::iterator iter = myMap.find(myString);
if(iter != myMap.end())
{
 iter->second.insert(myDouble);
}
Naveen