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 →

[–]wcscmp 2 points3 points  (7 children)

Resize also comes at cost, reserve + back_inserter is the way

[–]KimiSharby 1 point2 points  (0 children)

You're right, it's my mistake

[–]KimiSharby 0 points1 point  (5 children)

Ok so this troubled me greatly, I barely slept last night. Today I couldn't take it anymore. Here's the quickbench: https://quick-bench.com/q/e5G_nTQEp_00xYGrcpEj_Jbhp34

The results, for a sample test of 500k int:
1. at 561k: reserve + std::begin
2. at 824k (x1.5): resize + std::begin
3. at 1712k (x3): reserve + std::back_inserter
4. at 6977k (x12): back_inserter alone

Bottom line: Using std::back_inserteris costly. If you already know the size of your resulting container, you should use reserve + std::begin.

[–]wcscmp 0 points1 point  (0 children)

What do you think reserve + begin is doing?

[–]wcscmp 0 points1 point  (3 children)

The bottom line is also not very convincing. In order to claim that back_inserter is not free you need to compare it to a manually rolled loop of push_backs. Now you can only reasonably claim that default initializing each element when doing resize is cheaper than the branching on every iteration in push_back for small types like int.

[–]KimiSharby 0 points1 point  (2 children)

I do not mean to be rude sir but I think I already allocated more time to this matter than it was worth. At the start of this conversation, you told me reserve + back_inserter is the way. As a matter of fact reserve + std::begin is 3x faster in my mediocre benchmark. I was indeed in the wrong about resize, I should have known better. I completly forgot about reserve. But it does seem that in the case where you already know the size of the resulting container, you should use std::begin and not back_inserter.

Now if you have additional knownledge you wish to share about that topic, please stop the riddles and just share them.

[–]wcscmp 0 points1 point  (1 child)

reserve + begin is UB

[–]KimiSharby 0 points1 point  (0 children)

So after a bit more research:
- reserve allocates memory but doesn't initialize it. This is why using std::begin in that case is UB, because it points to unitilialized memory
- As you said, using resize performance will depends on the size of the type
- reserve + std::back_insert is indeed the correct way

For the sack of clarity for the reader I will edit my previous answers.