简体   繁体   中英

How are new std::map entries initialized just by key insertion?

I have one std::vector<MyString> which data is not unique. Actually, most strings are repeated. And I have to find the unique ones and their repeat number.

I use map:

std::map<MyString,unsigned short> stringsMap;
.......
if ( stringsMap.find( currentString ) == stringsMap.end() )
{
    stringsMap[ currentString ] = 0;
}

stringsMap[ currentString ]++;
........

Do you have ideas how it could be done on fewer lines?

It could be done on one row: stringsMap[ currentString ]++; however short has indeterminate value by default.

It could be done on one row: stringsMap[ currentString ]++; however short has indeterminate value by default.

This is not true, value is well defined as stated in documentation :

If an insertion is performed, the mapped value is value-initialized (default-constructed for class types, zero-initialized otherwise ) and a reference to it is returned.

emphasis is mine.

So it is perfectly fine to write one liner:

stringsMap[ currentString ]++;

and this is common practice and even given as an example in the documentation:

// count the number of occurrences of each word
// (the first call to operator[] initialized the counter with zero)
std::map<std::string, size_t>  word_map;
for (const auto &w : { "this", "sentence", "is", "not", "a", "sentence",
                       "this", "sentence", "is", "a", "hoax"}) {
    ++word_map[w];
}

however short has indeterminate value by default.

No. For a non existing key the map will use T() to initialize the value of the newly created entry, which effectively evaluates to 0 for unsigned short .

See the std::map::operator[] documentation (emphasis mine 1 ):

1) Inserts value_type(key, T()) if the key does not exist. This function is equivalent to return insert(std::make_pair(key, T())).first->second;
- key_type must meet the requirements of CopyConstructible .
- mapped_type must meet the requirements of CopyConstructible and DefaultConstructible .
If an insertion is performed, the mapped value is value-initialized (default-constructed for class types, zero-initialized otherwise ) and a reference to it is returned.

Thus, writing just

std::map<MyString,unsigned short> stringsMap;
.......
stringsMap[ currentString ]++;

is perfectly fine. The entire if block is redundant and not needed.


1) That's not really true, it was @Remy Lebau 's emphasis

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM