This is a consequence of the age-old "conflict of interest" between the functions std::list::size() and std::list::splice() .
If a partial splice() made from one std::list to another with the requirement of a constant execution time of such splice() (i.e., just transferring the extreme elements of the range from one list to another), then it will be impossible to immediately know the new dimensions of the container source and destination container, because it is not known how many elements are strung together Therefore, the requirement of a time- constant splice() leads to the requirement of a time- linear size() - elements in both containers will have to be recalculated.
If, on the contrary, to require time constancy size() (i.e., to actually require a stored size), then you have to agree to a slower splice() , which in the above situation will calculate the new sizes of containers for the linear time.
In C ++ 98 this question was left open. Implementations were allowed to choose where, in their opinion, the constant time is more important - in size() or splice() .
In C ++ 11 they decided to make a volitional decision: we make the stored size, guarantee size() for a constant time and, so be it, agree to linear time in splice() .
This explains the difference between C ++ 98 and C ++ 11.
PS The implementation of the standard C ++ library in GCC initially followed the fast splice() and slow size() paths. After C ++ 11 insisted on another version, GCC corrected the implementation of its std::list , but immediately stumbled upon the binary incompatibility of library versions due to the addition of a new field to std::list . The change was immediately rolled back, and to this day the std::list in the GCC does not meet the requirements of C ++ 11. std::list::size() is linear there.