85

What is the difference between the following two lines?

map<int, float> map_data;
map<const int, float> map_data;
iammilind
  • 68,093
  • 33
  • 169
  • 336
NullPoiиteя
  • 56,591
  • 22
  • 125
  • 143
  • Question is famillar with, http://stackoverflow.com/questions/6307321/does-it-make-sense-to-make-stdmap-key-const – soerium Jul 14 '13 at 17:31

7 Answers7

72
  • int and const int are two distinct types.

  • std::map<int, float> and std::map<const int, float> are, similarly, different types.

The difference between std::map<const int, float> and std::map<int, float> is, to a degree, analogous to the difference between, say, std::map<int, float> and std::map<std::string, float>; you get a fresh map type for each.

In the non-const case, the internal key type is still non-const int:

std::map<const int, float>::key_type       => const int
std::map<int, float>::key_type             => int

However, map keys are semantically immutable, and all map operations that allow direct access to keys (for example, dereferencing iterators, which yields value_type) does constify the key_type:

std::map<const int, float>::value_type => std::pair<const int, float>
std::map<int, float>::value_type       => std::pair<const int, float>

So the difference may be largely invisible to you in every way that matters, if your implementation allows it.

That's not always the case, though: the standard officially requires your key type to be copyable and moveable, and some implementations re-use map nodes; under those implementations, attempting to use a const key simply won't work.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
37

The key is already const, so it is redundant to write const in this case. Once an element is entered, its key cannot be changed.


Edit:

As mentioned in the comments, there is difference between the two lines. For example, if you write a function that accepts map<const int, int>, you can't pass to it map<int, int> since they're different types.

But note that although they are different types, they behave the same since the key in a map is a const anyway...

So in conclusion.. The only difference is that they are two different types, you shouldn't care about anything else.

Maroun
  • 94,125
  • 30
  • 188
  • 241
  • 18
    This is not (completely) correct. The interface of `std::map` exposes the key type as `const`, but that doesn't mean that the two template instantiations are the same as this answer might imply. `std::map` and `std::map` are [different types](http://coliru.stacked-crooked.com/view?id=d5261dd32220b034acffc54933351fac-f674c1a6d04c632b71a62362c0ccfc51). – jrok Jul 14 '13 at 10:00
  • 1
    @jrok is correct, whereas this answer is not. The `key_type` is in fact still `int` in the former case. – Lightness Races in Orbit Jul 14 '13 at 13:17
  • I edit my answer, I hope it's better now. Thanks for your comments and correction. – Maroun Jul 14 '13 at 13:28
  • @Maroun: Almost, but the key is _not_ `const` (i.e. `geordi << TYPE::key_type>; # int`). However, it is semantically immutable and all operations that directly access keys (for example, dereferencing an iterator) give you a `const`-ified version of the key value (i.e. `geordi << TYPE::value_type>; # std::pair`). – Lightness Races in Orbit Jul 14 '13 at 16:22
  • 6
    @johnmac2332: Let this be a lesson that fast != perfect, and upvotes != correct. – Lightness Races in Orbit Jul 14 '13 at 16:26
  • 1
    @johnmac2332 Fast and Quick answers should highly appreciated. This is one of the quality Stackoverflow better than other webs. OP can further query in comment section. if he say thanks means probably he got the answer. – Grijesh Chauhan Jul 14 '13 at 19:27
  • 2
    No one is perfect, we all do mistakes and learn from each other. We're here to learn and help :) – Maroun Jul 15 '13 at 08:05
  • @Grijesh: Unfortunately the OP may _think_ he got the answer, because it appeared plausible, but was in fact misled and will go on to spread the misinformation. Speed/haste is absolutely _not_ a substitute for correctness. Why is everyone in such a hurry!? – Lightness Races in Orbit Jul 15 '13 at 10:26
  • 1
    @Maroun: Speak for yourself - I'm here for the rep and glory! :) – Lightness Races in Orbit Jul 15 '13 at 10:26
  • 2
    @LightnessRacesinOrbit Ok, yes! I agree with you. Btw you posted a nice answer. And yes one should take time to post and to **accept** an answer. I myself most of time try to explain from fundamental and post long answers (but of-course delayed & low-voted posts). anyways, I congrats Maroun for his 10K RP. Maroun posted many good answers and I found him a valuable contributor. – Grijesh Chauhan Jul 15 '13 at 14:36
  • 1
    @GrijeshChauhan: Yes, likewise. This factual error is out of character! – Lightness Races in Orbit Jul 15 '13 at 15:44
9

The difference is that the second variant will set the key type for the map as const int. From the "modifiability" point of view this is redundant, since the map already stores its keys as const objects.

However, this can also lead to unexpected and non-obvious differences in the behavior of these two maps. In C++ a template specialization written for type T is different from specialization written for type const T. That means the above two versions of the map might end up using different specializations of various "satellite" templates that depend on the key type. One example is the key comparator predicate. The first one will use std::less<int> while the second one will use std::less<const int>. By exploiting this difference you can easily make these maps to sort their elements in different order.

Issues like that are more obvious with the new C++11 containers like std::unordered_map. std::unordered_map<const int, int> will not even compile, since it will attempt to use a std::hash<const int> specialization for hashing the keys. Such specialization does not exist in the standard library.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
3

const can't be altered once set. And yes as per docs & other answer you should remember that key is const already.

Link: http://www.cplusplus.com/reference/map/map/ Link: http://en.cppreference.com/w/cpp/container/map

AliciaBytes
  • 7,300
  • 6
  • 36
  • 47
Shumail
  • 3,103
  • 4
  • 28
  • 35
2

While the behaviour of your application will typically be the same, it makes a difference to some compilers you might use. The more specific example of what brought me to this page in the first place:

Explicitly specifying a map as map<const key, value> builds successfully with the gnu toolkit;

However it crashes a Studio12 Solaris x86 build.


map<key, value> builds successfully on both. Behaviour of the application is unchanged.

blgt
  • 8,135
  • 1
  • 25
  • 28
0

Const keys can be helpful if the keys are pointers. Using const keys won't let you modify the pointed object when accessing the keys, consider this:

#include <map>
#include <string>

int glob = 10;

int main() {
    std::map<const int*, std::string> constKeyMap { { &glob, "foo"} };
    std::map<int*, std::string> keyMap { { &glob, "bar" } };

    for(const auto& kv : keyMap) { *(kv.first) = 20; }; // glob = 20
    for(const auto& kv : constKeyMap) { *(kv.first) = 20; }; // COMPILE ERROR

    return 0;
}
SiimKallas
  • 934
  • 11
  • 23
  • 1
    When the `key_type` is `const int*`, the pointer itself it not const, but the pointed `int` is const. – lrineau Apr 02 '14 at 13:44
-1

const refers to a constant, that, once defined, can't be altered then... non const key is subjected to change... or cant even change, it's just that "no change" is guaranteed in const (once defined), and "change" may or may not occur in non const stuff.

r0u9hn3ck
  • 553
  • 4
  • 11