Let's consider this class:
class X {
std::map<uint32_t, uint32_t> _map;
public:
X() { /* Populate the map */ }
std::map<uint32_t, uint32_t> getTheMap() { return _map; }
};
and this buggy code:
X x;
// Statement 1
std::map<uint32_t, uint32_t>::const_iterator it = x.getTheMap().begin();
// Statement 2
std::map<uint32_t, uint32_t>::const_iterator et = x.getTheMap().end();
for (; it != et; it++) {
/* Access the map using the iterator it */
}
The wrong part is that, in Statement 1
and Statement 2
, I'm getting an iterator to a temporary object which is going to be destroyed at the end of each statement.
As a result the behavior inside the for()
loop is undefined.
A correct usage of the getTheMap()
method would have been this:
std::map<uint32_t, uint32_t> map = x.getTheMap();
std::map<uint32_t, uint32_t>::const_iterator it = map.begin();
std::map<uint32_t, uint32_t>::const_iterator et = map.end();
for (/* [...] */)
It must be noted that class X
has some serious design issues:
_map
should be better encapsulated inside the class (both for read and write access), so thegetTheMap()
method could be avoided- If the
getTheMap()
method is really needed, it could return a reference to_map
However, given class X "as is" (<-- see edit below), is there a way to prevent users from getting the iterator to the temporary?
EDIT: class X
can be changed, but getTheMap
method should exist and return by value. however I was also thinking about compiler warnings.