【问题标题】:Will initializing a const reference argument fom a default argument result in a dangling reference? [duplicate]从默认参数初始化 const 引用参数会导致悬空引用吗? [复制]
【发布时间】:2018-10-29 16:21:40
【问题描述】:
void foo(const std::string& s = "abc") {
    // ...
}

// ...

int main() {
    // ...
    foo();
    // ...
}

s 中的 foo 会悬空吗?我认为因为std::string 将由默认值"abc" 构造,然后这将是一个 const 引用做临时死。

我说的对吗?

【问题讨论】:

    标签: c++ lifetime


    【解决方案1】:

    s 不会在foo 中摇摆,但临时将在整个foo 中存在。要理解为什么会发生这种情况,需要理解以下几点:

    1. 当您在函数上声明默认参数时,默认参数将插入到调用站点。您编写的代码的行为与以下代码相同:

      void foo(const std::string& s) {
          // ...
      }
      
      // ...
      
      int main() {
          // ...
          foo("abc");
          // ...
      }
      

      所以std::string 临时在调用站点创建。

    2. 当临时std::string绑定到const std::string& s时,临时为lifetime extended。它将一直存在到完整表达式的末尾,即foo("abc"); 末尾的分号。

    综上所述,我们可以看到s 不会悬空,因为它指向一个临时字符串,该字符串至少与foo 执行的时间一样长。

    【讨论】:

      【解决方案2】:

      std::string(const char*) 的构造函数将用于构造一个临时函数,该临时函数将在函数的整个生命周期中存在。

      所以不会有问题。

      【讨论】:

        【解决方案3】:

        不,临时的生命周期将延长,直到包含对 foo 的调用的表达式的评估结束。如果s scape 函数体,那么它将是一个悬空引用。

        标准格式[class.temporary]/6.9

        在函数调用 (8.2.2) 中绑定到引用参数的临时对象一直存在,直到包含调用的完整表达式完成为止。

        【讨论】:

        • 注意until the call to foo return和completion of the full-expression containing the call.不一样
        • 是的,你是对的,我修正了答案中的措辞。
        【解决方案4】:

        不,临时将持续到包含对 foo 的调用的完整表达式的末尾,我们可以从草案 C++ 标准部分 [class.temporary]p6 中看到这一点:

        第三个上下文是当一个引用被绑定到一个临时对象时。38 如果通过以下方式之一获得引用绑定到的泛左值,则引用绑定到的临时对象或作为引用绑定到的子对象的完整对象的临时对象在引用的生命周期内持续存在:

        ...

        然后再往下说:

        此生命周期规则的例外情况是:
        - 在函数调用 ([expr.call]) 中绑定到引用参数的临时对象一直存在,直到包含调用的完整表达式完成。

        ....

        这就是我们这里的情况。有关until the completion of the full-expression 的说明,请参阅What is the lifetime of a default argument temporary bound to a reference parameter?。

        【讨论】:

          【解决方案5】:

          只要你不做类似的事情:

          const char* temp;
          void foo(const std::string& s = "abc") {
              temp = s.c_str();
          }
          

          或者像存储对这个 const ref 的引用之类的东西,你应该没问题。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-01-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-02-25
            • 2020-02-28
            • 2016-10-28
            • 1970-01-01
            相关资源
            最近更新 更多