【问题标题】:c++ return reference / stack memory [duplicate]c ++返回引用/堆栈内存[重复]
【发布时间】:2011-03-16 04:51:37
【问题描述】:

一个我不确定答案的基本问题。跟随功能有效吗?

std::vector<int> & test_function() {
   std::vector<int> x;

   // do whatever

   return x;
}

如果是这样,为什么?函数返回后程序不应该从堆栈中删除 x 吗?谢谢。

【问题讨论】:

    标签: c++ function stack


    【解决方案1】:

    行为未定义。您不应该返回对局部变量的引用。

    【讨论】:

    • 显示的代码(本身)不包含任何未定义的行为。 UB 会发生在调用此函数的其他代码中。
    【解决方案2】:

    函数格式正确(语法正确),但函数一返回,返回的引用无效,不能使用。

    澄清一下:有问题的代码调用任何未定义的行为。只要您不使用返回值,您就可以安全地调用此函数,例如,这是有效的:

    test_function(); // ok
    

    但是,如果您尝试使用返回值(即,用它初始化另一个引用或将所指对象复制到另一个对象中),那么您将调用未定义的行为,因为所指对象(对象 x)的生命周期将具有结束(函数返回时x会被销毁,因为它是一个自动变量):

    std::vector<int>& vec = test_function(); // undefined
    std::vector<int> vec = test_function();  // undefined
    

    【讨论】:

    • 严肃地说,如果被引用的结构只是一堆 POD(没有指针)或者是一个原语,如果持有正常的堆栈帧,并且您复制值(而不是持有参考它,所以你的第二个例子在这里),原始本地值将在返回后立即正常(mov esp,ebp; pop ebp; 本地堆栈帧不受干扰)。然而,析构函数被调用并且数据可以被操纵/改变。然而,这是错误的做法,并且预测会发生什么,即使在一个地方准确猜测也是不可移植的。
    • @jMerliN:即使对于 POD 类型的对象,结果也是形式上未定义的。 POD 的生命周期在其存储期限结束时结束;对于局部变量,这是函数返回的点。在对象的生命周期结束后使用它会导致未定义的行为。这可能在实践中对 POD 类型对象“起作用”吗?也许,但正如你所说,这不是应该依赖的行为。
    • 当多线程成为标准时,绝对不应该依赖它,因为堆栈帧的位置可能已经被另一个线程重用(注意标准没有定义堆栈或堆的位置实施)。
    【解决方案3】:

    是的,它是有效的,但是如果你尝试使用返回的值,你会得到未定义的行为。

    【讨论】:

      【解决方案4】:

      您不能返回对局部变量的引用,原因与不能返回指向局部变量的指针的原因相同,因为从函数返回时,这些局部变量被释放,因此引用或指针变得无效。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-15
        • 1970-01-01
        • 2014-05-22
        • 2012-09-23
        • 2020-04-24
        • 2012-04-12
        • 1970-01-01
        相关资源
        最近更新 更多