使用不同的引用返回tmp

时间:2013-04-12 09:52:58

标签: c++ reference

我知道使用引用返回临时变量不起作用,因为临时对象在函数终止后会丢失,但是由于返回的临时对象被分配给另一个对象,所以下面的代码可以正常工作。

我假设在函数调用行之后临时对象被销毁。如果是这样的话,为什么这种方法不能用于链接呢?

Counter& Counter::doubler()
{ 
   Counter tmp;
   tmp.i = this->i * 2;
   return tmp;
}

int main()
{
    Counter d(2);
    Counter d1, d2;
    d1 = d.doubler();                            // normal function call
    std::cout << "d1=" << d1.get() << std::endl; // Output : d1=4 
    d2 = d.doubler().doubler();                  // Method chaining
    std::cout << "d2=" << d2.get() << std::endl; // Output : d2=0 
    return 0;
}

6 个答案:

答案 0 :(得分:3)

如果函数返回对本地对象的引用,则该函数返回后将立即销毁该对象(如本地对象所示)。它持续到函数调用行的末尾。

在销毁对象后访问该对象将产生不可预测的结果。有时它可能有用,对于某些“工作”的定义,有时可能没有。只是不要这样做。

答案 1 :(得分:0)

Counter& doubler()
{ 
Counter tmp;
tmp.i=this->i*2;
return tmp;
}

这是未定义的行为。从函数返回后 - 您的引用将悬空,因为将为本地对象Counter调用tmp析构函数。

答案 2 :(得分:0)

您正在返回对本地(临时)对象的引用。退出函数后,它是未定义的行为。

因为tmp将在返回函数后被销毁。因此,返回的引用无效。

答案 3 :(得分:0)

真正的问题不是“为什么这种方法链不起作用?”而是“为什么第一个('正常')函数调用有效?”

答案是没有办法说出来,因为它可能会破坏你的程序。

要清楚说明:通过引用返回临时对象是未定义的行为。当然,这意味着它今天可能会巧合而且明天就会停止工作。所有赌注都已关闭。

答案 4 :(得分:0)

当函数返回并发生堆栈回滚时,逻辑回滚堆栈指针设置为不同的值。如果函数返回局部变量引用,则指向本地的内存位置可能仍处于进程中并且设置了相同的位。但是,这不能得到保证,并且在几次调用之后无效并且可能导致未定义的行为。

答案 5 :(得分:0)

其他都可以,因为“只是不要乱用本地对象的引用”

但至于为什么它适用于一个案例而不是其他案件

  1. 当你单独调用它时,当函数返回时,对象仍然躺在堆栈上。授予一个“被破坏的”对象 - 但是对象过去采取的任何空间仍然存在于堆栈中。如果你有一个简单的对象,比如一个int成员,那么堆栈上就会有令人不安的东西,除非你在堆栈上编写了其他东西的代码,或者析构函数决定做一个更彻底的工作并删除一个整数成员(大多数析构者都不这样做。雅达亚达,但直到下一行不会发生太大的事情,将其从堆栈中移出。你的引用指向一个有效的内存位置,你的(被破坏的)对象就在那里。这就是为什么它适合你。

  2. 当您将其称为链接时,请参阅第一个调用,返回对堆栈上该tmp的引用。正如上面#1中所解释的那样,到目前为止没问题。你的(破坏的)tmp仍然存在于堆栈中。但请注意你称之为第二个倍增器的那一刻。第二个双倍函数调用中的tmp会出现在哪里?就在你第一次通话的tmp !!!第二个调用使用值为0的tmp(默认构造的一个)覆盖对象(值为4的tmp)。第二个调用实际上是在一个具有0值的计数器上进行的,因此你得到0.非常棘手 - 这就是为什么忘记摆弄返回对局部变量的引用。

  3. 现在纯粹主义者可能尖叫 - 未定义,不,不,只是不这样做 - 我和他们在一起 - 我自己说了两次(现在三次)不这样做。但人们可能会尝试。我打赌像下面这样的'简单'对象,并且代码与问题完全相同(因此没有任何东西扰乱堆栈),每个人都会得到一致的4,0 - 没有随机性,没有未定义.... / p>

    class Counter
    {
    public:
        Counter()
        {
            i = 0;
        }
        Counter(int k)
        {
            i = k;
        }
        int get()
        {
            return i;
        }
        int i;
        Counter& doubler();
    };