Thread: return value of functions

  1. #1
    Registered User
    Join Date
    Aug 2001

    return value of functions

    assume this little code
    SomeObject my_func()
      return SomeObject(...); // 1
    void some_other_function()
      SomeObject so = my_func();
    what happens to the return value on return?
    so where does it exist? is it appended to top of stack of the calling function?
    or does it exist outside the stack frame of the caller (thus in the stack-frame of the callee which no longer exists then)?
    and how long is that return value valid - so when is the destructor of it called?

    immediately after the next operation (e.g. i _+_ func()) (in case there is one (e.g. func(); )?

    and how is that value returned? it seems that integers and floats are returned directly through a register.
    but what about objects? is the address of the returned object put into a register then?

    so does anyone know where to find an explanation (or could explain) of how functions return their value - and how long it stays valid (thus when is it destroyed), and how often and when it is constructed/destroyed during that process?
    signature under construction

  2. #2
    Registered User
    Join Date
    Nov 2001
    return doesnt exist after return

    verify via reference


  3. #3
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    United States
    When you call a function, a stack frame is established. This stack frame is a queue data structure made out of memory locations, and is built in the following way:

    1. The return address is put onto the stack. This is the address that the function will return to after it completes execution, it is also the address that contains the return type:
    2. On top of that is room for the return type.
    3. Then your function's arguments are placed on the stack.
    4. From here, the program branches out to your function and local variables are placed on the stack as they are defined.

    When your function returns, the reverse happens as the stack is destroyed, and you end up with the return variable being located on the caller's stack frame. Since the caller has not returned yet, this memory is still available to you.

    You must be careful that you do not return a pointer or a reference to stack memory. That is dangerous and results in the pointer or reference pointing to garbage.
    Last edited by whiteflags; 07-13-2006 at 12:52 PM.

  4. #4
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    It resides in the free-store. At least that's the interpretation I make from Strousptrup's 3rd Edition.

    When a function is called, store is set aside for its formal arguments (non reference and non pointer ones) and, I'm assuming, the return object (when this is not a reference or pointer). A return statement initializes an unnamed variable of the same type as that of the returned type. Type checking and conversions are done and the variable is then copied to the caller object. Next the store is reused, and thus the temp destroyed.

    Since non dynamically allocated objects are the only ones residing on the stack, I reckon the temporaries (arguments and return objects) are created on the free-store.

    EDIT: Ah! Citizen seems to have nailed it. Ignore my reply.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  5. #5
    Registered User
    Join Date
    Jan 2005
    There are two possible outcomes. The first is that a temporary SomeObject is created inside the function, and then passed to the copy constructor to create a second SomeObject instance "so". The temporary object inside the function is destructed after so is created.

    A second possibility is that the compiler will utilize return value optimization. In that case, instead of constructing a temporary SomeObject, it will construct "so" with the parameters specified in the function's return statement. It can do this since it is obvious that the temporary will only be used to constructo "so" and then go out of scope.

    The second possibility is probably more likely in the posted case.

    In the general case of a function that returns by value, the object returned goes out of scope after it is used as the return value.

    I'm not sure I follow the citizen's answer above completely, but I don't think it is correct. The object created inside the function is destroyed. As (apparently) kuphryn was trying to say, if you make "so" a reference variable, it will be referring to the temporary object returned from the function, which will be destroyed by the time you try to use "so".
    Last edited by Daved; 07-13-2006 at 12:56 PM.

  6. #6
    Registered User
    Join Date
    Aug 2001
    so what happens to the return type is, that simply the storage is allocated on the stack, but left uninitialized

    SomeObject func(arg0 -  argn) { ... }
    internally translates to something similar
     void func(arg0 - argn,  "sizeof(SomeObject) bytes") { ... }
    (so the last parameter is the one deepest in the stack - thus when the callee returns, the return value is the "top-of-stack" of the caller.

    so the layout would be:
    [ stack frame of the caller ] [ return value of the callee ] [return address] [ arg n ] ... [ arg 0] [ local variables of the callee]

    uh, wouldn't it make more sense pushing the return address AFTER the storage for the return type? since then everything can be cleaned up, leaving just the return value alone on top of the stack.

    or is the correct order really ... [return address] [return value of the callee] ?
    well in that case the extra few bytes of the return address need to be cleaned up too - not that this is a problem, but the other solution looks better - or are there problems with it?
    signature under construction

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    The edge of the known universe
    Are you trying to write a compiler?

    Both your ideas are equally plausable, it all depends on how the compiler writer has chosen to implement it.

    All that matters to you is that the result appears as an r-value which can be assigned to an l-value of the same (or compatible) type.
    Like so
    SomeObject so = my_func();

    If you're that keen to know, then I suggest looking at the asm output, with say
    gcc -S foo.cpp
    for objects of varying sizes.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    Aug 2001
    >> Are you trying to write a compiler?

    hehe, yes... once again - maybe this time i might even finish it
    well i'll implement the ordering [return value] [return adress], which just leaves the return value alone on the stack then.

    signature under construction

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. is it ok like that?
    By ExDHaos in forum C++ Programming
    Replies: 8
    Last Post: 05-23-2009, 09:02 AM
  2. DirectInput help
    By Muphin in forum Game Programming
    Replies: 2
    Last Post: 09-10-2005, 11:52 AM
  3. string class errors
    By CodeMonkey in forum C++ Programming
    Replies: 13
    Last Post: 07-20-2003, 11:20 PM
  4. OpenGL and Windows
    By sean345 in forum Game Programming
    Replies: 5
    Last Post: 06-24-2002, 10:14 PM
  5. oh me oh my hash maps up the wazoo
    By DarkDays in forum C++ Programming
    Replies: 5
    Last Post: 11-30-2001, 11:54 AM
Website Security Test