There are no heap or stack in the C++ language. These are properties of an implementation, not the language. An implementation is free to do whatever it wants as long as the resulting program does what the standard says it should do. This includes allocating storage for automatic variables or temporaries on the heap.
The "normal" implementations don't do that though. Both automatic variables and temporaries are allocated on the stack or in the registers.
In your example, all variables named result
have automatic storage duration, which usually means they are allocated on the stack (inasmuch the implementation has such thing as "the stack"—the language is silent about it). Copying from one variable to another does not normally involve any third variable or temporary that needs to be allocated somewhere. This includes the case of returning a value from a function.
An object may own resources such as memory, that need to be allocated on the free store ("heap" in terms of implementations that have a heap). If this is the case, then the copy constructor or the copy assignment operator take care of copying, and allocate stuff wherever needed. But this is about the resources owned by the object, not the object itself.
The question you link is about avoidance of copying, specifically avoidance of copying of the owned resources. This has little to do with any of the above.
An implementation is allowed, and sometimes required, to elide copies. Copy elision is one way to avoid copying. Here is an example:
#include <iostream>
struct Foo
{
Foo() {}
Foo(const Foo&) { std::cout << "Copied by ctor\n"; };
Foo& operator=(const Foo&) { std::cout << "Copied by assignment\n"; return *this; };
};
Foo func()
{
Foo foo;
return foo;
}
int main()
{
Foo foo (func());
}
Live demo. This example shows both mandatory and optional copy elision.
In C++14 and below, there are two cases of optional copy elision. In C++17 and above, there is one case of optional and one case of mandatory copy elision (a new feature in C++17, officially called "temporary materialization"). GCC performs optional copy elision by default but it can be disabled with -fno-elide-constructors
. It is an optimisation allowed by the standard. Mandatory copy elision cannot be disabled because the standard mandates it.
Another way to avoid copying is to use moving instead of copying when possible. Move semantics is a separate story which is beyond the scope of this answer.