f() returns an object reference; returning from it does not copy any object. g() returns a copy of the object, at least conceptually.
std::vector<int>& f1 = f();
f1 refers to the object to which f() returns a reference. No copies are made. The const-qualification of the link does not matter here (as far as copying is concerned, obviously this affects what can be done with the object).
std::vector<int> f2 = f();
f2 is a copy of the object to which f() returns a link.
std::vector<int>& g1 = g();
This is not true. A non-constant reference cannot be bound to a temporary object.
If the link is const-qualified, then this line actually matches the following line: the object returned by g() copied, the link is bound to this copy, and this copy is provided with the link lifetime (it is destroyed when the link is "destroyed").
std::vector<int> g2 = g();
g2 is a copy of the object returned by g() . Regardless of whether a copy is made (and how many copies can be made), it depends on the optimization of the compiler.
What if f() and g() are member functions, and each returns element data, rather than some local variable?
If f() returns a link to a local variable, then the program is incorrect and gives undefined behavior if you try to use the link because the linked object ceases to exist when the function returns.
If f() returns a link to a member variable, a dynamically allocated object, or an object with a static or local thread storage duration, then the link is valid for the lifetime of this object (or for another object of the same type constructed in the same memory location as and the object to which this link was returned, although its usefulness is limited to a few select scenarios).
It doesn't matter what g() returns, because the copy always executes (at least conceptually).