简体   繁体   中英

how does the function return in c++ work

I want to know how the compiler save this temporary int if I call the function f(3);

int f (int x) { return x; } 

and how this will be excuted by the compiler :

int a=f(3);

is it just like doing int a=x; (I know x will be already destroyed ) or it really create a temporary variable called f(3), like this int f(3)=x;

int& a=f(3);

and why this wont work ?

Function calls

The compiler will do one of the following things:

  1. Push the argument on stack and call the function
    • For a more complex function than yours, this will typically happen.
  2. Load the argument into a register and call the function
    • This may happen when optimizing, and there are enough registers to hold variables that need to be passed around.
  3. Optimize the function away completely (inlining)
    • For a trivial function like the one in your case, a sane compiler will do this with the most basic optimization level, so that you get the same assembly as if you did int a = 3 .

Reference variables in C++

A reference variable, one declared as int &a in your code is "a different name for an existing memory location". So declaring int &a does not allocate space for an int anywhere. It just declares a to refer to an already allocated memory location.

This location may be an existing variable int b , so that you say:

int b;
int &a = b;

Here, a will refer to the same contents that b refers to. "A new name for an existing object" is a good idiom to go with.

You could get fancy and say int &a = array[5] , so that a refers to 6th element of an int array array , or int &a = *(int*)0x12345678 to refer to a specific memory location, but I'm digressing.

Your code

int &a = 3;

cannot work, because 3 is a temporary object, which will be forgotten after the statement is executed. To understand the problem more fundamentally think of this: If a refers to an already allocated memory location, what will it refer to, after the statement int &a = 3 is executed, and there is no longer a temporary object 3 ?

This is also a common problem with reference variables in functions: returning a reference to a function-local object is undefined behavior... but I'm digressing again. You always have to have a "living, allocated object" for a to refer to, end of story.

A bit more in-depth on reference variables

What typically happens for a statement like

int a = 3;

is that the compiler generates code to (simplified):

  1. load the constant 3 to a register
  2. load the register to the memory location allocated for a

The point is: in either case, there is no long-lived memory location allocated for the object 3 , so an int &a really cannot be made to refer to this object because of that.

"long-lived memory location" means a location that will live past the assignment operation. The register where 3 is stored will be overwritten and reused probably immediately after the assignment operation, so it doesn't qualify even theoretically for the target of int &a (in practice, int &a can only be made to refer to a memory location, not a register, anyway).

  1. It depends on the calling convention. With cdecl (which is common), the function will return x in the EAX register. It will then be copied into the register assigned to a .

Of course, an optimizing compiler will optimize the whole thing to:

int x = 3;

2. You can't have a reference to something whose object lifetime has ended. The object lifetime of x ends when the function does.

Any reasonable compiler could (and would) turn

int a=f(3);

into

int a=3;

The call would initially compile into something like pushing the return address onto the stack, then the argument; the function itself would compile to popping the argument, popping the return address and pushing the argument again, then branching to the return address. A trivial optimizer would detect that no useful work was done, and optimize the whole thing away.

  1. When you call a function f(3) the instruction address of the calling statement gets saved in a register and your instruction pointer jumps to the address of the first statement of function f. Also a new stack frame for function f is pushed onto the stack. When the function call returns a temporary will be created for the returned int from f(3) and this is what will be assigned to x when you do int x=f(3); (so returned value from f is created in a temporary which is then copied into x) so yes a temporary is being created for the return. The stack created for f(3) is destroyed as well.

  2. int& a=f(3); doesn't work as a is a reference. A Reference is an alias. An alias is for something that already exists. f(3) returns a temporary copy to be assigned to a variable. As the stack is going to disappear after the f(3) call you can't really assign a reference onto that.

int& a=f(3); - what isn't fine about this is that you're creating a reference to a temporary variable . On function exit, the data the reference refers to has been cleared and so it's now a hanging reference.

It is likely the compiler will just treat int a = f(3); as int a = 3; in the situation you outlined, but you can never be certain since ultimately this depends on the specific compiler and how it performs its optimisations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM