Search code examples
c++stdlibstdc++libc++

One of them is not like the others: why is std::vector::size implemented in terms of pointers on all major standard library implementations?


Playing randomly on godbolt (as one does) I found that std::vector::size() is implemented as a difference of pointers while I was expecting it to just return a class data member. std::vector::capacity() is similar. What is weird is that all other standard containers (except std::deque) store the size as a data member. Even std::string on libstdc++ and Microsoft's STL stores its size as a data members (on libc++ it looks like size info storage is optimized with SSO info, still the size is explicitly stored and not computed as difference of pointers).

Here is the godbolt link with all the containers' size on libc++, libstdc++ and microsoft's STL. Some excerpts below:

f_vec4:  //std::vector<std::int32_t>
        mov     rax, qword ptr [rdi + 8]
        sub     rax, qword ptr [rdi]
        sar     rax, 2
        ret
f_vec8:  // std::vector<int64_t>
        mov     rax, qword ptr [rdi + 8]
        sub     rax, qword ptr [rdi]
        sar     rax, 3
        ret

f_list:
        mov     rax, QWORD PTR [rdi+16]
        ret

f_map:
        mov     rax, QWORD PTR [rdi+40]
        ret

Why is std::vector::size the only container size implemented as pointer difference while all other containers store their size? Is is something in the standard? Is it an optimization?


Solution

  • why is std::vector::size implemented in terms of pointers on all major standard library implementations?

    Because it can be implemented in terms of pointer subtraction. And because the standard library implementers chose to do that.

    Is is something in the standard?

    No. I'm sure that it would be standard conforming to store the size as a member.

    What is weird is that all other standard containers (except std::deque) store the size as a data member.

    This is hardly surprising. No other data structure can use pointers as iterators besides an array.

    std::string is implemented as an array, so it could also use pointer subtraction. If it isn't done so, it is because the implementers chose to not do so. This may, or might not be due to convenience related to small string optimisation.