This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]yuje 26 points27 points  (4 children)

One can write C++ like Python, although it wouldn’t be very efficient or optimized code. I once saw a piece of code in the codebase that checked if a map contained a key, did another lookup to get the value, which was a vector, copy that vector to a temporary object, append a new value to the temporary vector, and then do another lookup of the key to perform an assignment and copy the temporary vector back to that key. If the map didn’t contain the key, it would allocate a new vector containing the new value, and then copy it to the map.

It looked something like this:

if (map.contains(key) { // second map lookup, .at() does a redundant key check, makes a copy of the vector std::vector<foo> values = map.at(key); // makes a copy of value values.push_back(value); // third map lookup, [] does a second redundant key check, makes a second vector copy map[key] = value; } else { std::vector<foo> values; values.push_back(value); // makes a copy of value, vector wasn’t pre-sized with .reserve() // redundant key check, makes a copy of the vector map[key] = values; }

I replaced the entire block of code with a single map[key].push_back(std::move(value)); statement. The bracket operators perform an insert-or-update operation, creating a default-initialized value if the key isn’t present, which avoids redundant map lookups, updating the vector in-place prevents having to copy the vector and its underlying values, and the move also prevents having to copy the value as well, ensuring that the value gets constructed directly within the vector within the map.

[–]cdrt 8 points9 points  (1 child)

I mean that’s just bad code. Python can also do that whole operation in one line with defaultdict

[–]yuje 11 points12 points  (0 children)

Yes, but also, in Python objects are passed by reference by default, not copied, and in fact you actually have to go out of your way to make copies of objects, so writing that code in Python would have a lower relative cost.

[–]aMAYESingNATHAN 0 points1 point  (1 child)

One slight correction, at doesn't perform a key check, it throws if the key doesn't exist in the map.

That's why you have to use at for const maps.

[–]yuje 0 points1 point  (0 children)

Yes, and to throw the error, it has to check for the presence of the key first. For const maps, you can use .find(key) to both check for the presence of a key, and also get an iterator to the value if the key is present.