views:

132

answers:

2

What happens, step by step, when a variable is returned. I know that if it's a built-in and fits, it's thrown into rax/eax/ax. What happens when it doesn't fit, and/or isn't built-in? More importantly, is there a guaranteed copy constructor call?

edit: What about the destructor? Is that called "sometimes", "always", or "never"?

+7  A: 

Where the return value is stored depends entirely on the calling convention and is very architecture- and system-specific.

The compiler is permitted to elide the call to the copy constructor (i.e., it does not have to call the copy constructor). Note that returning a value from a function might also invoke an assignment operator, depending on what is being done with the return value of a function.

James McNellis
Is the destructor ever called for the local version?
Clark Gaebel
@wowus: No, because there isn't really a "local version." If the call to the copy constructor is elided, then the object being returned is constructed in-place in the return value.
James McNellis
@wowus: If there's no copy, calling the destructor will make that instance invalid.
KennyTM
What about code like... T f() { T a; return a; }
Clark Gaebel
@wowus: That might or might not invoke the copy constructor. I would expect that an unoptimized build (e.g., for debugging) would invoke the copy constructor, but an optimized build would not. It's entirely up to the compiler and what it decides is the most reasonable thing to do. If the copy constructor is not called, then obviously the destructor can't be called, per what @KennyTM and I said.
James McNellis
So if the copy constructor is called it is guaranteed to have a destructor call?
Clark Gaebel
@wowus: Yes, because all local objects are destroyed at the end of the block (e.g. when a function returns). If one of those objects is copied to be returned, then the local object still needs to be destroyed.
James McNellis
+2  A: 

If the function/method return type is a reference then effectively no copying takes place. If it is a non-reference return type, then a copy may take place depending on the calling convention of your platform.

In register-rich (typically RISC) architectures there may be a generous allocation of registers to hold modestly large return constructs. This is to avoid excessive memory transactions which are expensive compared to cache/register transactions.

On the x86-descended intel family which your question implies by the registers you mention, it is more likely than on a RISC to invoke a copy constructor.

Amardeep