v = foo();
The above statement is a move assignment (copy assignment for pre-C++11 compilers). In either case, the result of the call to foo()
is required for the assignment, since it is the input argument to the respective assignment operator, so the freeing of resources managed by v
is done after the call to foo()
, and the memory management is performed within the copy/move assignment operator.
Notice I didn't mention any calls to the destructor of v
, because the destructor will not be called at that point. The memory that is being managed by v
will be deallocated, with the destructors for the individual elements being invoked. In case of a vector<int>
, the destructor of each int
is a NOP, so they're only conceptually invoked.
The vector
will then allocate enough memory to be able to hold the contents of the vector
returned by foo
(copy assignment), or take control of the memory being managed by the vector
returned by foo
(move assignment). Of course, the vector
implementation is free to skip the deallocation followed by allocation if the existing memory is large enough to hold the new contents.
The destructor for v
will run when v
goes out of scope. In the example you've provided, this happens at the end of main()
.