返回引用并返回值

时间:2016-10-09 10:23:34

标签: c++ pointers reference

当我们返回本地随机变量的引用时,我不太清楚我已经理解为什么会出现问题。所以,让我们说我们有这个例子。

int *myFunc() {
  int phantom = 4;
  return &phantom;
}

然后通常的论点是,当使用函数时,变量phantom的内存在执行代码行int phantom = 4;后不再可用,因此无法返回(至少这个是我迄今为止所理解的)。另一方面,对于该功能,

int myFunc() {
  int phantom = 4;
  return phantom;
}

整数变量phantom的值将返回。 (我看到值的返回是变量phantom的底层指针的解除引用)。

我在这里想念什么?为什么在第一种情况下存在编译错误,在第二种情况下,一切都有效?

5 个答案:

答案 0 :(得分:2)

第一个不返回引用,它返回一个指针。一个指向局部变量的指针,一旦函数结束,它将超出范围,留下一个指向不再存在的变量的迷你指针。这就是为什么你得到编译器警告(通常不是实际错误)。

第二个代码复制该值。 return语句完成后,函数内的局部变量永远不需要被引用或使用。

答案 1 :(得分:0)

你不要错过很多。只有在第一种情况下才会出现编译器错误。

  

[...]执行代码行int phantom = 4后,变量模型的内存不再可用;所以它不能被退回

不,它可以返回,编译器可能会发出警告,但是没有错误。但是,你不应该!!

顺便说一下,内存是可用的,但是在返回函数后(而不是在行int phantom = 4;之后)访问它是未定义的行为。

在第二种情况下:

  

我看到值的返回是变量幻像的底层指针的解除引用

你在想这里太复杂了。从函数返回值可以通过使用指针来实现,但这是实现细节。你唯一需要关心的是返回的是。所以在第二种情况下没有问题。

答案 2 :(得分:0)

第一种情况

int* myFunc()
{
   int phantom = 4;
   return &phantom;  // you are returning the address of phantom
}                    // but phantom will not "exist" outside of myfunc

不起作用,因为变量phantom是一个局部变量,它只在myfunc执行期间存在。在那之后,它就消失了。

您正在返回一个变量的地址,这实际上将是#34;不存在"更多。

规则:永远不会返回指针或对局部变量的引用。

没关系:

 int myFunc()
 {
    int phantom = 4;
    return phantom;  // you are returning by value;
                     // it doesn't matter where phantom "lives"
 }                  

 int main()
 {
    int x = myFunc(); // the value returned by myFunc will be copied to x
 }

答案 3 :(得分:0)

  

我不太清楚我是否理解为什么会出现问题   我们返回一个局部随机变量的引用

因为如果您使用这样的函数,C ++标准说它是未定义的行为,并且您希望避免程序中未定义的行为。你的程序所做的应该由C ++语言的规则决定,而不是随机的。

请注意,您返回指针而不是引用。但在这两种情况下它都是未定义的行为。

  

然后通常的论点是当使用函数时,内存   变量phantom在执行后不再可用   代码行int phantom = 4;因此无法返回(至少这一点   是我迄今为止所理解的。)

这是一个以实现为中心的观点,可能帮助您理解问题。

然而,区分程序的可观察行为和编译器产生该行为的内部技巧是很重要的。你甚至不知道是否有任何内存被变量占用。考虑" as-if"规则和编译器优化,即使行为已定义,整个函数也可能已被删除。这只是幕后可能发生的事情的一个例子。

但是,无论如何,它还是未定义的行为,所以任何事情都可能发生。

那么问题是,当你返回这样的指针然后尝试访问指针对象时,为什么C ++标准没有为这种情况定义行为?答案就是它没有意义。当函数返回时,局部变量phantom命名的对象将终止它的生命。所以你会指向一个不再存在的东西,但它仍然是int*,解除引用非nullptr int*应该产生int 。这是一个矛盾,而C ++标准并不打算解决这种毫无意义的情况。

请注意,这种观察是基于C ++语言规则,不是关于编译器实现问题。

  

为什么在第一种情况下存在编译错误,在第二种情况下   案例一切正常吗?

它肯定是一个警告,而不是错误,除非您的编译器选项使每个警告都变成错误。编译器不能拒绝代码,因为it's not ill-formed

尽管如此,您的编译器仍尝试在第一种情况下提供帮助,因为它希望阻止您创建具有未定义行为的程序。

在第二种情况下,行为未定义。按值返回意味着副本由您要返回的对象组成。在销毁原件之前进行复制,然后调用者接收该副本。这不是没有意义的,也不是任何矛盾,所以它是安全和明确的行为。

在第一种情况下,按值返回对您没有帮助,因为虽然指针本身被安全复制,但其内容最终会导致未定义的行为。

答案 4 :(得分:-1)

尝试返回指针并取消引用它以获取值。

#include <iostream>

using namespace std;


int *myFunc()
{

    int number = 4;
    int *phantom = &number;

    return phantom;

}

int main()
{
    cout << myFunc() << endl; //0x....
    cout << *myFunc() << endl; //4
    return 0;
}