It's not that the non-constant version of front is called, it just stores pointers, and then you put it in auto , which always outputs by value (and not by reference - for which you need auto& = ). Since you are copying the const pointer, you have your own copy, so const is omitted for it unless you explicitly define it that way. This is why you TcpSocket* instead of TcpSocket* const .
If you want to check this out, try making auto& s = _sockets.front() and see what type you get.
Note. that since you are saving a pointer, the vector::const_reference that you return will point to a const pointer, not a pointer to const.
The container itself, which is a constant in this area, means that you cannot change your sequence of elements or what they point to. Therefore, you cannot say _sockets.erase() and you cannot say _sockets[0] . However, since the elements themselves are pointers to a non-const TcpSocket , this means that you can do whatever you want with them. This is a container that you cannot play with.
source share