Let's say there is a user defined class Foo. Some posts suggest that a C++ class object is "never" allocated on heap unless allocated with new. But! on the other hand there are posts that suggest that returning a local looking class object by value from function doesn't necessarily copy any data. So! where was the data of such an object stored in first place? Is it still stack? Did it get promoted to the stack frame of calling function?
class Foo {
...
}
Foo a(int x) {
Foo result;
doabc(x, result);
return result;
}
Foo b(int x) {
Foo result = a(x);
doxyz(x,result);
return result;
}
int main() {
int x;
cin >> x;
Foo result = b(x);
dosomethingelse(result);
cout << result;
}
If Foo result of from a is not copied by value, where is it allocated? Heap or stack? If on heap, does compiler automatically refactor the code to insert delete? If on stack which stack frame would it live on? b's? Here's the post that makes me wonder: https://stackoverflow.com/a/17473874/15239054. Thanks!
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
resulthave 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:
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.