繁体   English   中英

返回C ++堆栈变量

[英]returning C++ stack variable

在这个例子中,为什么返回堆栈变量是可以的? 当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;

}

输出:

./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

基本上,当您返回堆栈变量my_x调用复制构造函数来创建变量的新副本。 在这种情况下,这是不正确的,这要归功于所有强大的编译器

编译器使用一种称为返回值优化的技巧,方法是使变量my_x真正构造在main方法上为g分配的内存位置。 这就是为什么你看到打印相同的地址bfeb66d0 这避免了内存分配和复制构造。

有时由于代码的复杂性,这根本不可能,然后编译器重置为默认行为,创建对象的副本。

因为参数是按值传递的。 制作副本。 所以返回的不是堆栈上的值,而是它的副本。

好吧,返回一个副本,唯一不能返回它的副本是静态数组。 所以你不能这说......

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

    return arr;
}

编译器经过优化,可以在不调用复制构造函数的情况下处理返回的“堆栈变量”。 您唯一需要知道的是内存分配是在堆栈上分配它的函数和返回对象的函数的范围。

它不会调用复制构造函数,也不会分配两次。

可能存在一些特殊情况,当然这取决于编译器 - 例如,可以复制基元 - 但通常,在堆栈上分配的对象在返回时不会被复制。

例:

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