从默认参数初始化const引用参数会导致悬挂引用吗?

时间:2018-10-29 16:21:41

标签: c++ lifetime

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

// ...

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

s中的foo会晃来晃去吗?我认为,因为std::string是根据默认值"abc"构造的,所以这将是一个const引用,但会暂时终止。

我对吗?

5 个答案:

答案 0 :(得分:4)

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

所以不会有问题。

答案 1 :(得分:4)

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 :(得分:2)

否,将延长临时生存期,直到对包含对foo的调用的表达式的求值结束为止。如果s是函数主体,那么它将是一个悬空引用。

以标准语[class.temporary]/6.9

  

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

答案 3 :(得分:1)

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

  

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

     

...

然后进一步说:

  

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

     

....

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

答案 4 :(得分:0)

只要您不做类似的事情:

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

或者像存储对该const ref的引用之类的任何东西,您都应该没事。