简体   繁体   中英

returning C++ stack variable

In this example, why is it ok to return a stack variable? When t() returns, why is it not returning garbage, since the stack pointer has been incremented?

#include << string >>
#include << vector >>
#include << iostream >>

using namespace std;

class X{
public:

  X() { cout << "constructor" << endl; }

  ~X() { cout << "destructor" << endl; }

};

vector <X> t()
{
  cout << "t() start" << endl;

  vector<X> my_x;

  int i = 0;

  printf("t: %x %x %x\n", t, &my_x, &i);

  my\_x.push\_back(X()); my\_x.push\_back(X()); my\_x.push\_back(X());

  cout << "t() done" << endl;

  return my_x;
}

int main()
{

  cout << "main start" << endl;

  vector <X> g = t();


  printf("main: %x\n", &g);

  return 0;

}

output:

./a.out
main start
t() start
t: 8048984 bfeb66d0 bfeb667c
constructor
destructor
constructor
destructor
destructor
constructor
destructor
destructor
destructor
t() done
main: bfeb66d0
destructor
destructor
destructor

Basically when you return the stack variable my_x you would be calling the copy constructor to create a new copy of the variable. This is not true, in this case, thanks to the all mighty compiler .

The compiler uses a trick known as return by value optimization by making the variable my_x really being constructed in the place of memory assigned for g on the main method. This is why you see the same address bfeb66d0 being printed. This avoids memory allocation and copy construction.

Sometimes this is not at all possible due to the complexity of the code and then the compiler resets to the default behavior, creating a copy of the object.

Because parameters are passed by value. A copy is made. So what is being returned is not the value on the stack, but a copy of it.

Well a copy is returned, the only construct you can not return a copy of it is a static array. So you can not say this...

int[] retArray()
{
    int arr[101];

    return arr;
}

The compiler is optimized to handle returning "stack variables" without calling the copy constructor. The only thing you need to know about is that that memory allocation is in scope of both the function that allocated it on the stack and the function that the object is returned to.

It does NOT call the copy constructor nor does it allocate it twice.

There may be some special cases and of course it depends on the compiler -- for example, primitives may be copied -- but in general, objects allocated on the stack, don't get copied when being returned.

Example:

struct Test {

};

Test getTest() {
    Test t;
    std::cout << &t << std::endl;        // 0xbfeea75f
    return t;
}


int main(int argc, char *argv[])
{
    Test t = getTest();
    std::cout << &t << std::endl;       // also 0xbfeea75f
}

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