views:

1898

answers:

6

Hey!!

I am starting again with c++ and was thinking about the scope of variables. If I have a variable inside a function and then I return that variable will the variable not be "dead" when it's returned because the scope it was in has ended?

I have tried this with a function returning a string and it did work. Can anyone explain this? Or at least point me to some place that can explain this to me please.

Thanks

+1  A: 

The local variable is copied to the return value. Copy constructors are called for non-trivial classes.

If you return a pointer or reference to a local variable you will have trouble---just as your intuition suggested.

dmckee
+2  A: 

When you return a value, a copy is made. The scope of the local variable ends, but a copy is made, and returned to the calling function. Example:

int funcB() {
  int j = 12;
  return j;
}

void A() {
  int i;
  i = funcB();
}

The value of j (12) is copied and returned to i so that i will receive the value of 12.

Kieveli
+1  A: 

It really depends on what kind of variable you are returning. If you return a primitive then it is returned by copy, not by reference so the value is copied to the top of the stack (or, more often placed into a register) where the calling function can get it. If you allocate an object or memory on the heap and return a pointer then it doesn't die because it's on the heap, not the stack. If you allocate something on the stack, however, and return it, that would be a bad thing. For instance, either of these would be very bad:

int *myBadAddingFunction(int a, int b)
{
    int result;

    result = a + b;
    return &result; // this is very bad and the result is undefined
}

char *myOtherBadFunction()
{
    char myString[256];

    strcpy(myString, "This is my string!");
    return myString; // also allocated on the stack, also bad
}
Jason Coco
I am actually returning a string.. it's not exactly an array but I am declaring it in the function like so:string funcnam(parms...) {string test;<code... code>return string;}And it's doing ok
AntonioCS
If it's an actual string object it does fine because it's getting allocated on the heap, not on the stack. In the bad example above myString isn't actually an object, just a standard char array. CMS's Stack and Heap article is very good, you should give it a read :)
Jason Coco
+9  A: 

When the function terminates, the following steps happen:

  • The function’s return value is copied into the placeholder that was put on the stack for this purpose.

  • Everything after the stack frame pointer is popped off. This destroys all local variables and arguments.

  • The return value is popped off the stack and is assigned as the value of the function. If the value of the function isn’t assigned to anything, no assignment takes place, and the value is lost.

  • The address of the next instruction to execute is popped off the stack, and the CPU resumes execution at that instruction.

The stack and the heap

CMS
That's a nice article! I bookmarked it for sharing with people learning about the stack :)
Jason Coco
+1  A: 

Just for a little bit more of a memory-model oriented explanation: when a function is called, a temporary space is made for the function to put its local variables, called a frame. When the function (callee) returns its value, it puts the return value in the frame of the function that called it (caller), and then the callee frame is destroyed.

The "frame is destroyed" part is why you can't return pointers or references to local variables from functions. A pointer is effectively a memory location, so returning the memory location of a local variable (by definition: a variable within the frame) becomes incorrect once the frame is destroyed. Since the callee frame is destroyed as soon as it returns its value, any pointer or reference to a local variable is immediately incorrect.

cdleary
A: 

This depends on the type of the returned item. If you are returning by value, a new copy of the variable is made to return to the caller. I thins case you do not need to worry about object lifetime, but you may need to worry about the costs of copying objects (but please don't prematurely optimze - correctness is much more important):

std::string someFunc( std::string& const s)
{
    return s + "copy";
}

If the function is returning a reference, then you need to be careful about what you're returning because it's lifetime needs to extend beyond the function's lifetime and the caller will not necessarily be able todelete it if you're using new to create the object:

std::string& someFunc2( std::string const& s)
{
    return s + "reference to a copy";   // this is bad - the temp object created will 
                                        //  be destroyed after the expression the 
                                        //  function call is in finishes.
                                        //  Some, but not all, compilers will warn 
                                        //  about this.
}

Of course, returning pointers will have similar lifetime considerations.

Michael Burr