Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shocked by the strange behavior of unordered_map

It is a very simple piece of code:

#include <cstdio>
#include <unordered_map>

int main() {  
    std::unordered_map<int, int> m;
    m[1] = m.find(1) == m.end() ? 0 : 1;
    printf("%d\n", m[1]);
    return 0;
}

If the map does not contain 1, then assign m[1]=0; otherwise m[1]=1. I tried this with different gcc compilers here.

gcc5.2 always outputs 1, gcc7.1 always outputs 0.

Why is it so different? Shouldn't it be 0 always? I cannot understand this behavior. What is the safest way to write such logic?

like image 397
LaoMao Avatar asked Jun 17 '17 02:06

LaoMao


People also ask

How do I make my unordered map faster?

reserve(1024); mp. max_load_factor(0.25); With this two lines unordered_map become about 10 times faster. You can replace 1024 with another suitable power of two.

Is unordered map faster?

TL;DR. in this test, the unordered map is approximately 3 times as fast (for lookups) as an ordered map, and a sorted vector convincingly beats a map.

Are HashMap and unordered_map same?

Yes, HashMap in java and unordered_map in c++ stl are more or less the same… you can store pointers in java too(Don't forget, in java, everything you deal with is a reference)… hence, HashMap also serves your purpose. unordered_map will do your purpose as well as hashmap in java will do .

What does unordered_map return?

unordered_map at() in C++ unordered_map :: at(): This function in C++ unordered_map returns the reference to the value with the element as key k.


1 Answers

The result is dependent on whether the compiler supports C++ 2017 or not.

According to the C++ 2017 Standard (5.18 Assignment and compound assignment operators)

1 The assignment operator (=) and the compound assignment operators all group right-to-left. All require a modifiable lvalue as their left operand and return an lvalue referring to the left operand. The result in all cases is a bit-field if the left operand is a bit-field. In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression The right operand is sequenced before the left operand.. With respect to an indeterminately-sequenced function call, the operation of a compound assignment is a single evaluation

On the other hand according to the C++ 2014 Standard (5.18 Assignment and compound assignment operators)

1 The assignment operator (=) and the compound assignment operators all group right-to-left. All require a modifiable lvalue as their left operand and return an lvalue referring to the left operand. The result in all cases is a bit-field if the left operand is a bit-field. In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression. With respect to an indeterminately-sequenced function call, the operation of a compound assignment is a single evaluation.

As you can see the statement in bold is absent in the quote from the C++ 2014 Standard.

So you should not rely on the order of the evaluation of the left and the right operands.

like image 171
Vlad from Moscow Avatar answered Oct 04 '22 22:10

Vlad from Moscow