6 ms·
> But if vec contains eg long strings, you've now murdered your perf because you're copying them out of the array instead of grabbing refs. I've seen much mor
by jcelerier 10mo ago
> But if vec contains eg long strings, you've now murdered your perf because you're copying them out of the array instead of grabbing refs.
I've seen much more perf-murdering things being caused by
std::map<std::string, int> my_map;
for(const std::pair<std::string, int>& v: my_map) {
...
}
than with auto though
- dubi_steinkek 10mo agoWhy is this a perf footgun? As someone who doesn't write a lot of c++, I don't see anything intuitively wrong. Is it that iterating over map yields something other than `std::pair`, but which can be converted to `std::pair` (with nontrivial cost) and that result is bound by reference?
- nemetroid 10mo agoClose, it is a std::pair, but it differs in constness. Iterating a std::map<K, V> yields std::pair<const K, V>, so you have: std::pair<const std::string, int> vs std::pair<std::string, int>
- 1718627440 10mo agoAnd what does casting const change, that would involve runtime inefficiencies?
- gpderetta 10mo agoIt is not a cast. std::pair<const std::string, ...> and std::pair<std::string,...> are different types, although there is an implicit conversion. So a temporary is implicitly created and bound to the const reference. So not only there is a copy, you have a reference to an object that is destroyed at end of scope when you might expect it to live further.
- 1718627440 10mo agoI guess this is one of the reasons, why I don't use C++. Temporaries is a topic, where C++ on one side and me and C on the other side has had disagreements in the past. Why does changing the type even create another object at all? Why does it allocate? Why doesn't the optimizer use the effective type to optimize that away?
- jcelerier 10mo ago> Why does changing the type even create another object at all? There's no such thing as "changing the type" in c++. Function returns an object type A, your variable is of type B, compiler tries to see if there is a conversion of the value of type A to a new value of type B
- nemetroid 10mo agoEach entry in the map will be copied. In C++, const T& is allowed to bind to a temporary object (whose lifetime will be extended). So a new pair is implicitly constructed, and the reference binds to this object.
- verall 10mo agoWow I really thought this would be a compile error. The implicit cast here really is a footgun. Looks like '-Wrange-loop-construct' (included in -Wall) does catch it: > warning: loop variable 'v' of type 'const std::pair<std::__cxx11::basic_string<char>, int>&' binds to a temporary constructed from type 'std::pair<const std::__cxx11::basic_string<char>, int>' [-Wrange-loop-construct] 11 | for (const std::pair<std::string, int>& v: m) { As they say, the power of names...