繁体   English   中英

返回引用并返回值

[英]Returning a reference and returning a value

我不太确定我是否理解我们返回局部随机变量的引用时为什么会有问题。 所以说我们有这个例子。

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

那么通常的论据是,当使用该函数时,在执行代码行int phantom = 4;后,变量phantom的内存不再可用int phantom = 4; 因此无法将其返回(至少到目前为止,这是我所了解的)。 另一方面,对于功能,

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

整数变量phantom的值将返回。 (我将值的返回视为对变量phantom的基础指针的取消引用)。

我在这里想念什么? 为什么在第一种情况下出现编译错误,而在第二种情况下一切正常?

第一个不返回引用,而是返回一个指针。 指向局部变量的指针,一旦函数结束,该变量将超出范围,从而给您留下一个不再存在的变量的流浪指针。 这就是为什么您会收到编译器警告 (通常不是实际错误)的原因。

第二个代码复制该值。 一旦return语句完成,函数内的局部变量将不再需要引用或使用。

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

在执行代码行int phantom = 4之后,变量phantom的内存不再可用。 所以不能退货

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

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

在第二种情况下:

我看到值的返回是变量幻影的基础指针的取消引用

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

第一种情况

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

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

您将返回一个变量的地址,该地址实际上将不再“存在”。

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

还行吧:

 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
 }

我不太确定我是否理解我们返回局部随机变量的引用时为什么会出现问题

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

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

那么通常的论据是,当使用该函数时,在执行代码行int phantom = 4;后,变量phantom的内存不再可用int phantom = 4; 因此无法将其返回(至少到目前为止,这是我所了解的)。

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

尽管如此,区分程序的可观察行为与编译器产生该行为的内部技巧之间的区别很重要。 您甚至都不知道某个变量是否占用了任何内存。 考虑“假设”规则和编译器优化,即使已定义了行为,也可能已删除了整个功能。 那只是幕后真正发生的事情的一个例子。

但同样,它仍然是未定义的行为,因此任何事情都可能发生。

问题是,当您返回这样的指针然后尝试访问指针时,为什么C ++标准没有为这种情况定义行为? 答案是没有意义的。 函数返回时,由局部变量phantom命名的对象将终止其寿命。 因此,您将拥有一个不再存在的指针,但它仍然是一个int* ,并且取消引用非nullptr int*应该会产生一个int 这是一个矛盾 ,而C ++标准只是不愿意解决这种无意义的情况。

请注意,此观察结果如何基于C ++语言规则, 而不是基于编译器实现问题。

为什么在第一种情况下出现编译错误,而在第二种情况下一切正常?

这当然是警告,而不是错误 ,除非您的编译器选项使每个警告都变成错误。 编译器不得拒绝代码,因为它的格式不正确

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

在第二种情况下,行为不是未定义的。 按值返回意味着您要返回的对象是一个副本 该副本是在销毁原始副本之前完成的,然后呼叫者会收到该副本。 这不是没有意义,也不是任何矛盾,因此它是安全且明确的行为。

在第一种情况下,通过价值回归不帮你,因为虽然指针本身安全的复制,它的内容是什么最终导致不确定的行为。

尝试返回指针并将其取消引用以获取该值。

#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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM