【问题标题】:Parameter passed by const reference returned by const reference由 const 引用传递的参数由 const 引用返回
【发布时间】:2009-03-20 18:34:43
【问题描述】:

我正在阅读 C++ 常见问题解答第二版,常见问题解答编号 32.08。

FAQ 说 const 引用传递和 const 引用返回的参数会导致悬空引用。

但是如果参数通过引用传递并通过引用返回也可以。

我知道在 const 引用的情况下它是不安全的,但是在参数是非 const 引用的情况下它是如何安全的。

FAQ 的最后一行说 “请注意,如果函数通过非常量引用接受参数(例如,f(string& s)),则返回此引用参数的副本是安全的,因为临时引用不能通过非常量引用传递。”

需要对此有所了解!

【问题讨论】:

标签: c++


【解决方案1】:

如果你喜欢

const Foo & bar(const Foo &f) { return f; }

然后这样称呼它

const Foo &ret = bar(Foo());

这可以编译,但问题是现在 'ret' 是一个悬空引用,因为调用 Foo() 创建的临时对象在 bar 返回后被释放。这里详细的执行顺序是:

  1. 临时 Foo 已分配
  2. 使用临时对象的引用调用 bar
  3. bar 返回引用
  4. 现在 bar 已返回临时 Foo 已释放
  5. 随着对象被破坏,引用现在悬空

但是,如果您将 Foo 声明为

Foo & bar(Foo &f) { return f; }

那么你的调用 bar(Foo()) 不会被编译器接受。将临时对象传递给函数时,只能通过 const 引用或作为副本来获取;这是语言定义的一部分。

【讨论】:

  • Editing: 'ref' 应该是 'ret' 所以这意味着 const Foo & 可以临时绑定到 Foo() 但 Foo & 不能绑定到 Foo() 临时。知道为什么编译器不允许这样做吗?
  • 这是不允许的,因为非常量引用必须引用命名对象。这主要是为了安全,但也有更多的理论原因。如果像 int 这样的非类临时值可以绑定到非常量引用,则 int 需要一个地址(作为对象)。但它不是一个对象 - 只是一个值
  • 将临时对象绑定到常量引用不会延长其生命周期吗? (参见ScopeGuard
【解决方案2】:

可以通过 const 引用传递临时对象 - 当函数返回时,临时对象被销毁,因此调用者留下了一个悬空引用。

例如:

#include <iostream>

using namespace std;

int const& output( int const& x) 
{
    cout << x << endl;

    return x;
} 

int main ()
{
    int a = 1;

    int const& ref1 = output( a); // OK

    int const& ref2 = output(a+1); // bad

    return 0;
}

【讨论】:

    【解决方案3】:

    我认为这个例子会有所帮助:

    const int& f(const int& n)
    {
        return n;
    }
    
    int f1(int& n)
    {
        return n;
    }
    
    
    int main(int argc, char **argv)
    {
        //Passing a reference to an anonymous object created by
        //the compiler to function f()
        const int& n = f(10);
    
        //Undefined behavior here as the scope of the anonymous object
        //was only till previous statement
        int k = n + 10;
    
        //Compiler error - Can not pass non-const reference to a anonymous object
        int n = f1(10);
    }
    

    【讨论】:

      【解决方案4】:

      Here 是一个关于 C++0x 右值引用的页面,开头是对左值和右值在 C++ 中如何工作以及如何允许它们与引用绑定的相当不错的总结。

      您会发现大多数关于 C++0x 中右值引用的文章都会让您对此有所了解。

      【讨论】:

        猜你喜欢
        • 2012-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-09
        • 1970-01-01
        相关资源
        最近更新 更多