Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: How can I stop map's operator[] from inserting bogus values?

Tags:

c++

map

stl

My code did the following:

  1. Retrieve a value from a map with operator[].
  2. Check the return value and if NULL use insert to insert a new element in the map.

Magically, an element with value 0 appeared in the map.

After several hours of debugging I discovered the following: map's operator[] inserts a new element if the key is not found while insert does not change the value if the key exists.

Even if a default constructor for the map value type does not exist the code compiles and operator[] inserts 0.

Is there a way (e.g. some coding convention I could follow from now on) I could have prevented this from hurting me?

like image 654
Christoph Wurm Avatar asked Nov 29 '22 09:11

Christoph Wurm


1 Answers

Is there a way (e.g. some coding convention I could follow from now on) I could have prevented this from hurting me?

This may sound snarky, but: by reading the documentation.

Since what you did is somewhat expected behaviour of the map, there’s not much you can do to guard against it.

One thing you can heed in the future is the following. In your second step, you did something wrong:

Check the return value and if NULL use insert to insert a new element in the map.

This does never work with C++ standard library functions (other than C compatibility functions and new): the standard library doesn’t deal in pointers, least of all null pointers, so checking against NULL (or 0 or nullptr) rarely makes sense. (Apart from that, it wouldn’t make sense for a map’s operator [] to return a pointer in the first place. It obvoiusly returns the element type (or rather, a reference to it)).

In fact, the standard library predominantly uses iterators so if at all, check for iterator validity by comparing against the end() of a container.

Unfortunately, your code (checking against NULL) compiled since NULL is actually a macro that’s equal to 0 in C++ so you can compare it against an integer.

C++11 gets safer by introducing the nullptr keyword which has a distinct type, so comparing it with an integer wouldn’t compile. So this is a useful coding convention: never use NULL, and instead compile with C++11 support enabled and use nullptr.

like image 62
Konrad Rudolph Avatar answered Dec 10 '22 10:12

Konrad Rudolph