返回一个引用并返回一个值

Returning a reference and returning a value

本文关键字:返回 一个 引用      更新时间:2023-10-16

我不太确定我是否理解了当我们返回一个局部随机变量的引用时为什么会出现问题。假设我们有这个例子。

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

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

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

返回整型变量phantom的值。(我认为该值的返回是对变量phantom的底层指针的解引用)。

我错过了什么??为什么在第一种情况下有一个编译错误,在第二种情况下一切工作??

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

第二段代码复制该值。一旦return语句结束,函数内部的局部变量将永远不需要被引用或使用。

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

[…在执行代码行int phantom = 4后,变量phantom的内存不再可用;所以不能返回

不,它可以返回,编译器可能会发出警告,但不会出错。然而,你不应该!!

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

第二种情况:

我将该值的返回视为变量phantom

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

我不太确定我是否理解了为什么会有问题返回一个局部随机变量

的引用。

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

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

那么通常的参数是,当使用函数时,内存变量phantom的值在执行后不再可用代码行int phantom = 4;,所以它不能返回(至少这个

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

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

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

问题是,那么,为什么c++标准没有为这种情况定义一种行为,当你返回一个像这样的指针,然后尝试访问指针?答案是,这没有意义。由局部变量phantom命名的对象在函数返回时结束其生命。因此,您将有一个指向不再存在的东西的指针,但它仍然是int*,并且解引用非nullptr int*应该产生int。这是一个矛盾,而c++标准根本懒得解决这种无意义的情况。

注意这个观察结果是基于c++语言规则的,不是关于编译器实现问题。

为什么在第一种情况下有编译错误,而在第二种情况下万一一切顺利??

这当然是一个警告,而不是错误,除非你的编译器选项使每个警告都变成错误。编译器不能拒绝代码,因为它不是病态的。

但是,在第一种情况下,你的编译器试图提供帮助,因为它想要阻止你创建一个具有未定义行为的程序。

在第二种情况下,行为不是未定义的。按值返回意味着由你想要返回的对象组成一个副本。在原始文件被销毁之前生成副本,然后调用方接收该副本。这不是毫无意义的,也不是矛盾的,所以这是安全的,明确的行为。

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

第一个case

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

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

你返回的是一个变量的地址,这个变量实际上将"不再存在"。

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

This is OK:

 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
 }

尝试返回指针并对其解引用以获得值。

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