10

I noticed that the QMap::operator[](const Key & key) has these two overloads:

    T & QMap::operator[](const Key & key)
const T QMap::operator[](const Key & key) const

Is there a reason for returning by value?

And since we have move semantics:

when returning by value, should we ever return by const value?

The reason why I am asking is this:

Imagine we have:

class ExpensiveToCopy;
{
public:
    int someProperty() const;
    ...
}

void f(const QMap<int, ExpensiveToCopy>& map)
{
    int lala = map[4].someProperty(); // We need to copy the entire object
                                      // just to look at someProperty();
}
Martin Drozdik
  • 12,742
  • 22
  • 81
  • 146

3 Answers3

12

In the the const case we can not add an element to the const map if it does not already exist, so a local object will be returned.

Otherwise, in the non-const case, an element will be created with the specified key (if there isn't one already) before returning a reference to it.

Joe
  • 6,497
  • 4
  • 29
  • 55
Andrii
  • 1,788
  • 11
  • 20
  • 3
    This is exactly it. I was just about to write the same answer. Note `std::map` has no `const operator[]`, and it is probably a good thing. Less confusing. – juanchopanza Aug 29 '13 at 06:50
  • Specifically: the `const` case must be able to return a "default" constructed element without inserting anything into the map in case an element with the given key isn't found in the map. So it cannot return a reference. – juanchopanza Aug 29 '13 at 06:53
  • @juanchopanza It could return a reference to a static local variable, so it is possible to return a const reference. Whether one wants to, is a different matter... – Sjoerd Aug 29 '13 at 09:10
  • @Sjoerd True. Also, this doesn't explain why a `const` value is returned. I think it is a bad idea to have the `const` overload, unless you are willing to introduce bound checks. – juanchopanza Aug 29 '13 at 09:59
  • @juanchopanza they probably made the value `const` so that something like `const_map['k'].someMutatingMemberFn()` doesn't happen, where the intent was to modify the object contained in the map, not the temporary, which makes sense in C++98 but is a bad idea in C++11 (as it prevents move). Preventing such abuse is still possible in C++11 via reference qualifiers. See also http://stackoverflow.com/questions/16834937/isnt-the-const-modifier-here-unnecessary – Joe Aug 29 '13 at 11:07
0

I think non reference const is to ensure client code can't modify map by any ways. you know if use const_cast<ExpensiveToCopy>map[4] or other ways, we still can modify map[4], but this map[4] is not reference to 4th element of map.

john zhao
  • 986
  • 1
  • 6
  • 8
0

It's also not possible to store a Value type with const members, since returning by value requires Value::operator=(). It seems to me the const version of QMap::operator[] is ill-conceived. The same effect could be produced by calling contains() and at(). This is an example of a convenience function that is, well, inconvenient.