6

我目前正在阅读有关C++的内容,并且我读到在使用按引用返回时,我应该确保我没有返回对函数返回时将超出范围的变量的引用。

那么为什么在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。

4

3 回答 3

7

这是未定义的行为,它似乎可以正常工作,但它可能随时中断,您不能依赖该程序的结果。

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

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

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

于 2013-08-23T18:42:02.937 回答
1

可能发生的事情(再次,对于 UB,任何事情都会发生)是因为在您调用 之后Add,您没有调用其他任何东西,还没有任何内容覆盖原来的内存cen,因此旧值仍然存在。话虽这么说,你不能依赖总是发生的事情。

于 2013-08-23T18:41:55.517 回答
1

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

于 2013-08-23T18:42:35.573 回答