简体   繁体   English

返回C ++堆栈变量

[英]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? 当t()返回时,为什么它不返回垃圾,因为堆栈指针已递增?

#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. 基本上,当您返回堆栈变量my_x调用复制构造函数来创建变量的新副本。 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. 编译器使用一种称为返回值优化的技巧,方法是使变量my_x真正构造在main方法上为g分配的内存位置。 This is why you see the same address bfeb66d0 being printed. 这就是为什么你看到打印相同的地址bfeb66d0 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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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