The quoted text is pointing out that there is an object whose value is set to the return value of the function: with C++17's guaranteed elision when returning by value, that object will be something like a variable being created by the caller, an element in a vector the caller is emplacing or push_backing too, or an object being constructed in some dynamically allocated memory the caller's orchestrated. You're confusing this with a temporary, which as you say might not be involved.
Working through it systematically, you quote cppreference saying of...
return expression;
...that...
If expression is a prvalue, the object returned by the function is initialized directly by that expression. This does not involve a copy or move constructor when the types match
The C++17 Standard says in [basic.lval]:
The result of a prvalue
is the value that the expression stores into its context. [ ... ] The result object of a prvalue
is the object initialized by the prvalue
; a prvalue
that is used to compute the value of an operand of an operator or that has type cv void
has no result object. [ Note: Except when the prvalue
is the operand of a decltype-specifier, a prvalue
of class or array type always has a result object. For a discarded prvalue
, a temporary object is materialized; ...
So, in the cppreference text, what the standard terms the "result object" is being referred to as "the object returned by the function". The language is a little bit imprecise in saying the result object is "returned" rather than "initialised", but overall it's not misleading and - for having avoided yet another bit of terminology - may well be easier for most cppreference readers to understand. I'm not actively involved with the site, but as a regular user my impression is that cppreference is trying to accurately explain the essence of the standard but simplifying language a smidge when possible.
While the underlying mechanisms are left unspecified by the Standard - and the practicalities of optimisation / ABIs dictate different implementation - to get a sense of what the Standard requires happen functionally it might help to imagine the compiler implementing code like...
My_Object function() { return { a, b, c }; }
...
... {
My_Object my_object = function(); // caller
}
...by secretly passing a memory-for-returned-object address to the function (much like the this
pointer to member functions)...
void function(My_Object* p_returned_object) {
new (p_returned_object) My_Object{ a, b, c };
}
So, there is an object involved and constructed by the called function, but its whereabouts is elided - i.e. a caller-specified memory address. If the function call result is unused by the caller, a temporary is at least notionally constructed then destructed.