将const引用参数初始化为默认参数会导致悬空引用吗
Will initializing a const reference argument fom a default argument result in a dangling reference?
void foo(const std::string& s = "abc") {
// ...
}
// ...
int main() {
// ...
foo();
// ...
}
foo
中的s
会悬空吗?我认为,因为std::string
将由默认值"abc"
构造而成,然后这将是一个常量引用,所以是暂时的。
我说得对吗?
s
不会挂在foo
中,但临时将在整个foo
中存在。有几个部分需要理解才能理解为什么会发生这种情况:
-
在函数上声明默认参数时,默认参数将插入调用站点。您编写的代码的行为与以下代码相同:
void foo(const std::string& s) { // ... } // ... int main() { // ... foo("abc"); // ... }
因此,在呼叫站点创建了
std::string
临时。 -
当临时
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的引用的操作,都应该是可以的。
- 将const引用参数初始化为默认参数会导致悬空引用吗
- 具有常量引用参数的函数模板专用化
- C++:常量引用参数
- 字符串引用参数的效率C++
- 通过非常量引用参数修改常量引用参数
- 如何将指针变量作为引用参数传递?
- C++初始化 std::function 时如何将占位符绑定到引用/引用参数?
- 移动类的成员作为常量引用参数传递
- C++带有适用于左值和右值的引用参数的函数
- constexpr 函数的常量引用参数:gcc/msvc vs clang/icc
- 如何使用类型特征将函数的通用引用参数限制为 r 值引用?
- 委托构造函数和引用参数
- 对 const 引用参数使用默认值会导致崩溃
- 为什么我们不允许将纯引用参数传递给 std::thread,但允许传递原始指针?
- 为什么我需要将默认引用参数定义为 const 以便为其分配一个左值?
- 将非左值作为常量引用参数传递.临时是在本地作用域还是在调用方作用域中创建的?
- 如何强制函数仅接受左值引用参数
- 模板引用参数推断失败C++
- 非类型引用参数可以在运行时修改,这是否意味着模板可以在运行时实例化?
- 将unique_ptr作为引用参数或常量传递unique_ptr引用