STL map class

Started by
4 comments, last by null_pointer 23 years, 9 months ago
I am using a STL map to map unsigned ints to images. My image class has all the appropriate copy constructors defined, but the default constructor leaves the object with no filename and thus no bitmap in memory. Why does the following pseudo-code call my image default constructor and then the copy constructor? // images - a std::map&ltunsigned int, image> // copy the 0-index image images[0].copy(other_image, ...); The copy function is never executed (yet), so I know it is not causing the problem. I can''t make heads or tails of the STL source code, because it is mostly inline and very hard to read. I can do this fine with the map::find function, but that''s kind of messy... Thanks! - null_pointer Sabre Multimedia
Advertisement
The reason is that [] on map works like find _AND_ insert, to do this the code goes something like:


map::operator[] (key)
{
if(key not in map)
{
insert key and a default construct value
}

return refrence to value for key
}

So it first calls the default constructor, then returns a reference that you can assign to. This also makes maps slower than using find or insert directly. You should use insert instead, e.g.

images.insert( make_pair(0, whatever));

Edited by - Wilka on July 21, 2000 5:11:10 PM
Wilka:

The value of ''0'' already has an image associated with it in the list of images. So I am wondering why in the world it is trying to insert a new image if one is already present? I simply want to look up the existing image.


image myimage("default.bmp");
images.insert(image_container_type::value(0, myimage));
images[0].copy(...);



It works fine until I hit the operator[], which should simply return a reference to myimage, right? Instead, the default constructor is called, and then the copy constructor on the object constructed with the default constructor. According to the docs, it should just return find() if the object is already in the map, right?



- null_pointer
Sabre Multimedia
Hmmm, that does seem a bit odd.

I checked operator[] for std::map, and it''s defined like this:

quote:
_Tref operator[](const key_type& _Kv)
{iterator _P = insert(value_type(_Kv, _Ty())).first;
return ((*_P).second); }


value_type is pair(const _K, _Ty) (I''m using brackets instead of greater & less so you can see them in the post).

The return value of insert is a pair. ''first'' is an iterator to the element inserted (or the existing one if it''s already there) and ''second'' is a bool. true means the element was inserted, false means it wasn''t.

So when you use [] on a map it calls insert with the key passed in and a default constructed value (i.e. _Ty()). Then it returns a reference to ''second'' (the value type) of the iterator returned from insert.

I didn''t realise this happened with std::map (I thought it called find, then insert if needed), but most of the time I use insert and find so it''s never affected me.

So it looks like you''ll have to use find instead of [] if you don''t want a default constructor to be used. e.g.

image myimage("default.bmp");images.insert(image_container_type::value(0, myimage));images.find(0)->second.copy(...); 


It''s a bit more code and isn''t as easy to read as using [], but at least you now it''s faster and it doesn''t need to create a temp object.
Wilka:

Thanks, but I know how to use find.

Anyway, what I don't understand is that, when I use the [] operator, passing it a key for an element that _is_ in the map, two constructors are called. Besides the temp object, a copy of the temp object is constructed. That copy of the invalid object is what crashes my drawing routine.

Why the second copy?

I'll just go back to using find...



- null_pointer
Sabre Multimedia


Edited by - null_pointer on July 22, 2000 12:21:44 PM
The second copy is because pair needs to copy the constructor parameters to its member variables (first & second).

This topic is closed to new replies.

Advertisement