【问题标题】:question on function returning a reference in C++关于在 C++ 中返回引用的函数的问题
【发布时间】:2010-09-01 17:45:02
【问题描述】:

可以从函数返回对局部变量的引用吗?本地我的意思是变量将在函数内创建(在堆栈上,即不使用 new),其范围仅在该函数内。当我搜索这个时,我得到了相互矛盾的答案。 1) 说这种用法是正确的,但 2) 与之相矛盾。

1) http://functionx.com/cpp/examples/returnreference.htm
2) http://www.cprogramming.com/tutorial/references.html(在参考和安全部分下)

哪一个是对的?

我的另一个问题是,如果 1) 是正确的,那么以下是否有相同的目的。

i) int& a = func();
ii) int a = func();其中 func() 返回对 int(该函数中的局部变量)的引用。

在上述两种情况下,都没有涉及到返回值的复制,不是吗。我想防止复制返回值,因为返回值可能很大。

提前谢谢你。

拉格瓦。

【问题讨论】:

  • 除了在整个 C++ 代码中传播错误之外,我不知道您得到的第一个参考是要做什么。不要相信它。
  • 链接 (1) 肯定是错误的。链接(2)我没有看到areturn by reference。
  • 男孩,functionx 的东西很臭。他们的代码质量的线索是在他们的主页“1900 年 9 月 1 日,星期三 11:19:59 AM”

标签: c++ reference


【解决方案1】:

正如其他人所说,不要那样做。返回指向局部变量的引用或指针总是错误的,因为返回的行为摆脱了局部变量,因此引用或指针自动无效。

复制可能不是问题。 C++ 编译器允许在从函数返回时跳过复制构造函数(“返回值优化”),因此足够聪明的编译器可能能够在适当的位置构建值。因此,您很可能能够在不进行任何复制的情况下返回一个较大的值。试试看;您可以暂时将输出语句放在复制构造函数中(如果您已经编写了一个并且没有使用自动生成的),以查看它是否实际被调用。

因此,如果不运行和尝试,您将不知道是否存在实际复制,如果存在,那么问题有多大。与往常一样,运行时间和配置文件以查看是否有问题,如果有,在哪里。在计时和分析之前,做任何有风险和/或令人困惑的事情来提高性能几乎是不值得做的。

【讨论】:

    【解决方案2】:

    您可以在函数中返回对静态局部变量的引用。否则,这将导致灾难,因为一旦函数返回,局部变量就会被破坏。

    Following 可能会有所帮助,它采用了您在第一次参考中引用的相同示例。

    编辑 2:

    对于您帖子中的第 ii 点,让我们假设一个函数“fn”,如图所示

    int& fn(){
    static int x;
    return x;
    }
    
    int a = fn();
    

    这涉及从表达式“fn”的左值复制。

    不涉及副本,如果是的话

    int &a = fn();
    

    【讨论】:

    • @chubsdad:谢谢你的链接。这基本上与我在这里提出的问题相同,甚至那里的海报也指向我提到的相同链接。
    【解决方案3】:

    如果您的意思是函数内部的变量,不……返回对它的引用总是无稽之谈。从成员函数返回对成员变量的引用非常好。

    关于希望避免复制大型数据结构。请等到您有实际的个人资料数据表明您是 a) 实际制作副本,并且 b) 它实际上是一个瓶颈。 “过早的优化是万恶之源”可能有点极端,但过早的优化肯定会带来很多痛苦和麻烦,而且很少(如果有的话)真正提供这些尝试旨在实现的任何好处。

    【讨论】:

    • 是的,我的意思是函数内部(本地)的变量。我会更具体地编辑我的帖子。
    【解决方案4】:

    您在第一个链接中看到的示例完全是假的。 functionx.com 上的那个页面是垃圾。返回对本地(自动)变量的引用始终是错误的,因为任何访问返回值的尝试都将导致未定义的行为。

    第二个链接是正确的。

    【讨论】:

      【解决方案5】:

      从函数返回对非静态局部变量的引用是绝对不行的。当函数返回时,变量超出范围,因此引用将引用已销毁的对象。

      虽然这在 1) 中提供的第一个示例中可能看起来“有效”,但这种不良做法很快就会让您对具有析构函数或更大的类感到失望。

      最好是返回一个指针,返回一个局部静态对象的引用,返回一个成员变量的引用。

      在这种情况下,如果对象是在要返回的函数内部构造的,您可能会考虑在您的大类上实现 C++ 0x 移动语义。这可能能够将“大副本”转换为几个指针交换。

      【讨论】:

      • 通过“返回指针”,我假设您的意思是指向动态分配对象的指针。返回指向局部函数变量的指针与返回引用的问题完全相同。
      • 并且通过“返回指针”,我假设您的意思是一个 RAII 对象 包含 一个指针。 ;) 至于实现移动语义,我假设您的意思是如果您观察到复制实际发生并且还观察到它导致了瓶颈。
      • @Noah:如果是按值返回肯定会发生复制对吧?
      • @Raghava - 事实上,没有。见 12.8/15
      • @Noah:谢谢你的指点。稍后,我会使用分析器并检查是否有任何性能损失。
      【解决方案6】:

      假设 func 返回一个对函数返回后的值的引用(静态本地或全局),那么您的

      i) int& a = func();
      ii) int a = func(); where func() returns a reference to an int (local variable in that function).
      

      完全不同

      在(i)中a仍然是指静态的或全局的。改变 a 会改变原来的变量

      在(ii)a是一个本地副本,改变它对原始变量没有影响

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-06-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-13
        相关资源
        最近更新 更多