Memory is freed up based on a “chunk”. It is possible that when you use a list, the memory is fragmented into small tiny bits.
When distributed using a vector, all elements are stored in one large fragment, so for the memory deallocation code it is easy to say "Golly, I have a very large free region here, I'm going to release it back to the OS." It is also quite possible that when growing a vector, the memory allocator switches to the “big piece” mode, which uses a different distribution method than the “small part mode” - for example, you allocate more than 1 MB, the memory allocation code can see that as a good time, to start using a different strategy and just ask the OS for a "perfect fit" of memory. This large block is very easy to release back into the OS when it is released.
In your ohter hand, if you add to the list, you constantly ask for small bits, so the allocator uses a different strategy for requesting a large block and issuing small portions. It is difficult and time-consuming to ensure that ALL the blocks in the block are freed, so the distributor may well not be “worried” because there are chances that there are some regions that are “still in use” and then it can “anyway.”
I would also add that using the “vertex” as a measure of memory is not a particularly accurate method and very unreliable, since it very much depends on what the OS and the execution library do. The memory belonging to the process may not be "resident", but the process still has not freed it - it simply is not "present in real memory" (instead, in the swap section!)
And to your question “is it defined somewhere”, I think it is in the sense that the original third C / C ++ library defines it. But he did not define in the sense that somewhere he wrote that "it should have worked like that, and we promise never to deceive him." Libraries supplied in the form of glibc and libstd ++ will not say that they will change the internal functions malloc, free, new and delete, because new technologies and ideas have been invented - some of them can improve the situation, others can make the situation worse, for this scenario.
As noted in the comments, memory is not blocked by the process. If the kernel feels that memory is better used for something else [and the kernel is omnipotent here], then it will “steal” the memory from one running process and transfer it to another. Especially a memory that has not been touched for a long time.