为什么返回对自动变量的引用有效?

时间:2013-08-23 18:36:25

标签: c++ reference return undefined-behavior

我目前正在阅读 C ++ ,我读到当使用return by reference时我应该确保我没有返回对超出范围的变量的引用函数返回。

那么为什么在Add函数中通过引用返回对象cen并且代码正常工作?!

以下是代码:

#include <iostream>
using namespace std;

class Cents
{
 private:
 int m_nCents;

 public:
 Cents(int nCents) { m_nCents = nCents; }

int GetCents() { return m_nCents; }
};

Cents& Add(Cents &c1, Cents &c2)
{
   Cents cen(c1.GetCents() + c2.GetCents());
   return cen;
}

int main()
{
   Cents cCents1(3);
   Cents cCents2(9);
   cout << "I have " << Add(cCents1, cCents2).GetCents() << " cents." << std::endl;

   return 0;
}

我在Win7上使用CodeBlocks IDE。

3 个答案:

答案 0 :(得分:7)

这是undefined behavior,它似乎可以正常工作,但它可以随时中断,你不能依赖这个程序的结果。

当函数退出时,用于保存自动变量的内存将被释放,并且引用该内存无效。

3.7.3 第1段中的C ++标准草案说:

  

显式声明寄存器或未显式声明为static或extern的块范围变量具有自动存储持续时间。 这些实体的存储会一直存在,直到创建它们的块退出。

答案 1 :(得分:1)

可能发生的事情(再次,UB,任何事情发生)是因为在你打电话给Add之后,你没有再调用任何其他东西,没有任何东西覆盖了cen的内存片段是的,所以旧的价值仍然存在。话虽如此,你不能完全依赖于那种情况。

答案 2 :(得分:1)

您应该使用memcpy将要返回的对象复制到堆中。尽管代码有效,但在返回超出范围的对象时,行为是未定义的。当代码很小时它总是可以工作,因为当函数返回时,函数占用的堆栈部分将不会被清除,并且因为函数中的局部变量将在那里分配空间,所以你得到的值(通常)包含您期望的值。但是当你有多个函数相互调用并且程序变大时,你的程序将开始产生未定义的行为。有时甚至可能会发生故障。