I’m reviewing a piece of code and see a class where an std::vector is stored as a member variable and the size of that std::vector is stored as a separate member variable. Both std::vector and its “stored copy” of size are never change during the containing object lifetime and the comments say size is stored separately “for convenience and for cases when an implementation computes the size each time“.
My first reaction was “WT*? Should’t it be always trivial to extract std::vectors size?”
Now I’ve carefully read 23.2.4 of C++ Standard and can’t see anything saying whether such implementations are allowed in the first place and I can’t imagine why it would be necessary to implement std::vector in such way that its current size needs non-trivial computations.
Is such implementation that std::vector::size() requires some non-trivial actions allowed? When would having such implementation make sense?
I would guess that your definition of “trivial” doesn’t match that of the author of the code.
If
sizeisn’t stored, I’d expectbeginandendto be stored, andsizeto be computed as the difference of the two, and that code to be inlined. So we’re basically talking two (nearby) memory accesses and a subtraction, instead of one memory access.For most practical purposes, both of those are trivial, and if the standard library author thinks that the result of that computation isn’t worth caching, then personally I am happy to accept their opinion. But the author of that code comment might think otherwise.
IIRC the standard says somewhere that
size“should” be O(1), not sure if that’s in the text for sequences or for containers. I don’t think it anywhere specifies that it must be forvector. But even if we read that as a non-requirement there’s a fundamental QOI issue here – what on earth am I doing optimizing my code for such a poor implementation at the expense of normal implementations?If someone uses such an implementation, presumably that’s because they want their code to run slowly. Who am I to judge otherwise? 😉
It’s also possible that the author of the code has profiled using a number of
end-beginimplementations, and measured a significant improvement by caching the size. But I think that’s less likely than that the author is being too pessimistic about the worst case their code needs to handle.