我正在研究一个fraction
类作为CS赋值,并编写了以下代码:
fraction fraction::add(fraction other) {
fraction temp;
/* manipulate temp */
return temp;
}
这非常有效,创建了一个新的fraction
对象,然后将其返回给调用代码。
问题是,为什么这样做了?当temp
方法返回并因此被销毁时,我的分数add
应该超出范围,但它会被传递回调用代码,而不会出现错误。
为什么返回具有本地范围的内容会导致它在超出范围后继续存在?
答案 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,temp
和returned
实际上是同一个对象,根本不会执行任何复制。