【问题标题】:Using a const reference to a returned by value value对按值返回的值使用 const 引用
【发布时间】:2011-05-24 08:08:09
【问题描述】:

看下面的例子:

string foo(int i) {
  string a;
  ... Process i to build a ...
  return a;
}

void bar(int j) {
  const string& b = foo(j);
  cout << b;
}

我知道 RVO 和 NRVO,但我认为为了做到这一点,我需要将 bar 写成如下:

void bar(int j) {
  string b = foo(j);
  cout << b;
}

两个版本似乎都可以工作,而且我相信具有相同的性能。 使用第一个版本(带有 const 引用)是否安全?

谢谢。

【问题讨论】:

    标签: c++ reference return-value rvo nrvo


    【解决方案1】:

    为 const 引用分配一个临时值是完全有效的。临时对象将一直存在,直到引用超出范围。

    虽然在您的示例中没有意义,但此功能通常用于函数参数:

    string foo(int i) {
        string a;
        // ...
        return a;
    }
    
    void bar(const string& str) {
        // ...
    }
    
    void buzz() {
        // We can safely call bar() with the temporary string returned by foo():
        bar(foo(42));
    }
    

    【讨论】:

    • 编译器将如何实现?它会避免展开foo 的局部变量使用的堆栈部分吗?如果foo 使用了大量的堆栈空间怎么办?
    【解决方案2】:

    在这种简单的情况下是安全的。但是,添加使其不安全的代码很容易,而且任何了解 C++ 的人都会感到困惑:为什么在这里需要参考?没有理由这样做,通常应避免使用此类代码。

    【讨论】:

    • 如果我将来将 foo 更改为返回 const & 会很有用。
    • 如果您更改 foo 的语义,您可能需要更改的内容远不止这些。
    【解决方案3】:

    允许const-reference绑定到临时,临时的live-time将延长到const-reference的live-time。所以是的,它可以安全使用。

    【讨论】:

      【解决方案4】:

      使用第一个版本(带有 const 引用)是否安全?

      是的。将临时对象绑定到 const 引用会将临时对象的生命周期延长到引用本身的生命周期,即声明引用的范围:

      void f()
      {
         const string& a = foo(10);
      
         //some work with a
      
         {
           const string& b = foo(20);
      
           //some work with b
      
         } //<----- b gets destroyed here, so the temporary also gets destroyed!
      
         //some more work with a
      
      } //<----- a gets destroyed here, so the temporary associated 
                                        //with it also gets destroyed!
      

      Herb Sutter 在他的文章中详细解释了这一点:

      A Candidate For the “Most Important const”

      值得一读。必读。

      【讨论】:

        猜你喜欢
        • 2023-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-15
        • 1970-01-01
        • 1970-01-01
        • 2012-11-03
        相关资源
        最近更新 更多