将const引用参数初始化为默认参数会导致悬空引用吗

Will initializing a const reference argument fom a default argument result in a dangling reference?

本文关键字:引用 参数 默认 const 初始化      更新时间:2023-10-16
void foo(const std::string& s = "abc") {
// ...
}
// ...
int main() {
// ...
foo();
// ...
}

foo中的s会悬空吗?我认为,因为std::string将由默认值"abc"构造而成,然后这将是一个常量引用,所以是暂时的。

我说得对吗?

s不会挂在foo中,但临时将在整个foo中存在。有几个部分需要理解才能理解为什么会发生这种情况:

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

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

    因此,在呼叫站点创建了std::string临时。

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

将这些放在一起,我们可以看到s不会挂起,因为它指向一个临时字符串,该字符串将至少与foo执行的时间一样长。

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

所以不会有任何问题。

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

标准语[临时等级]/6.9

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

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

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

然后说进一步向下:

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

这就是我们这里的情况。有关until the completion of the full-expression的说明,请参阅临时绑定到引用参数的默认参数的生存期是多少?。

只要你不做类似的事情

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

或者任何类似于存储对此const-ref的引用的操作,都应该是可以的。