返回对象和范围

时间:2013-10-22 18:24:56

标签: c++ function return

我正在研究一个fraction类作为CS赋值,并编写了以下代码:

fraction fraction::add(fraction other) {
    fraction temp;

    /* manipulate temp */

    return temp;
}

这非常有效,创建了一个新的fraction对象,然后将其返回给调用代码。

问题是,为什么这样做了?当temp方法返回并因此被销毁时,我的分数add应该超出范围,但它会被传递回调用代码,而不会出现错误。

为什么返回具有本地范围的内容会导致它在超出范围后继续存在?

2 个答案:

答案 0 :(得分:6)

您将返回temp的值,而不是temp对象本身。该值被复制并返回给调用函数,temp然后被销毁的事实与此无关。

就是这样:

int a;
{
    int b = 5;
    a = b;
}
std::cout << a << std::endl;

在结束括号后,b已超出范围,但a仍然包含值5,并且没问题。你的函数调用大概发生了同样的事情。

如果将指针返回给本地对象,那么这是一个非常不同的故事。尝试取消引用该指针将调用未定义的行为,因为您正在尝试访问不再存在的对象。但是,当您只使用返回的值时,该对象是否存在并不重要,因为此时您只拥有自己包含的值的副本。 (从技术上讲,它仍然按值返回,在这里,调用函数中的指针将只包含它自己驻留的本地对象的地址副本 - 你只是不能对它做任何有用的事情,因为它的生命周期以前驻留在该地址的对象已经结束。)

答案 1 :(得分:4)

它不会继续存在。您返回值temp被复制(或在C ++ 11中移动)到任何函数的返回值,然后temp超出范围并被销毁。

或者,在大多数实现Return Value Optimization的现代编译器中,temp实际上与您分配函数返回值的对象相同,但不会消失范围。

看一个简单的例子

fraction value;
fraction other_value;
fraction returned = value.add(other_value);

当调用value.add(other_value)时,它会在成员函数的范围内构造temp,然后一旦到达行return temp;temp就会被复制到returned中在呼叫者范围内。现在return语句已经完成,函数结束,temp超出范围并被销毁。

对于RVO,tempreturned实际上是同一个对象,根本不会执行任何复制。