【问题标题】:Reference to variable out-of-scope引用变量超出范围
【发布时间】:2020-12-24 10:36:27
【问题描述】:

我做了以下例子来测试我对引用的理解:

#include <iostream>

int test(){
    int a = 1;
    int &b = a;
    return b;
}

int main(int argc, const char * argv[]) {
   
    std::cout << test() << std::endl;
}

我打算做的是写一个引用变量被销毁的例子。我最初写这个的想法是,由于test 中的a 的生命周期在test 中返回b 时结束,所以输出test 的返回值会产生乱码。然而,令我大吃一惊的是,它实际上输出了 1!

这怎么可能?我在这里错过了什么 - a 可以以某种方式继续生活在 b 中吗?

【问题讨论】:

  • 你的函数返回一个值而不是一个引用
  • 顺便说一句,即使您使用无效的引用,您也无法区分乱码 1 和非乱码 1
  • 通常很难避免 U.B.而不是介绍 U.B.但无论如何:demo on coliru
  • ab 都不存在。您的函数返回a 中值的副本。在您了解(默认情况下)函数的返回值是副本而不是引用之前,您似乎正在尝试理解引用。如果您希望test 真正返回引用,那么int&amp; test()

标签: c++ scope reference return-type function-definition


【解决方案1】:

该函数不返回对任何对象的引用。它返回一个由 b 引用的值复制初始化的 int 类型的临时对象。

int test(){
    int a = 1;
    int &b = a;
    return b;
}

其实这个函数在不使用中间变量的情况下相当于下面的函数

int test(){
    return 1;
}

返回引用意味着函数返回类型应该是引用类型。类似的东西

int & test()
{
    int a = 1;
    return a;
}

在这种情况下,编译器将发出一条消息,指出函数返回对局部变量的引用。

【讨论】:

  • 在最后一种情况下,编译器可能发出一条消息。该行为实际上是未定义的,这意味着不需要诊断。实际上,默认情况下,大多数现代编译器在这种情况下不会发出任何消息 - 但可以配置为(例如,使用命令行选项发出更多警告)。
【解决方案2】:

我明白你的困惑来自哪里。你认为,因为你在 b 的赋值过程中使用了 (&) 运算符,所以变量 b 现在包含 a 的内存地址。情况并非如此,与号 (&) 是静音的,这意味着在这种情况下它对变量 b 没有影响。

int test()
{
int a = 1;
int &b = a;
return b;
}

您期望的行为如下所示

int* test()
{
int a = 1;
int *b = nullptr;
b = &a; 
return b;
}

在这种情况下,您在不取消引用变量的情况下返回 b,那么您将获得内存地址而不是数字 1。

【讨论】:

  • “和号 (&) 引用 b 的地址;” 不知道你的意思。 b 是对 a 的引用,&amp; 在这种情况下不是操作员地址。请注意:您的第二个 sn-p 的返回类型错误。
猜你喜欢
  • 2016-04-30
  • 1970-01-01
  • 1970-01-01
  • 2016-09-16
  • 2016-03-05
  • 1970-01-01
  • 1970-01-01
  • 2021-10-04
  • 1970-01-01
相关资源
最近更新 更多