void foo(const std::string& s = "abc") {
// ...
}
// ...
int main() {
// ...
foo();
// ...
}
foo
中的 s
会成为悬空指针吗?我认为是因为 std::string
将从默认值 "abc"
构造,然后这将是一个 const 引用到已死临时对象。
我的理解正确吗?
s
不会在foo
中挂起,但是临时变量将在整个foo
生存期内存在。理解为什么会发生这种情况需要理解一些要点:
When you declare a default argument on the function, the default argument is inserted at the call site. The code you wrote behaves the same as the following code:
void foo(const std::string& s) {
// ...
}
// ...
int main() {
// ...
foo("abc");
// ...
}
So the std::string
temporary is created at the call site.
When the temporary std::string
is bound to the const std::string& s
, the temporary is lifetime extended. It will live until the end of the complete expression, i.e. the semicolon at the end of foo("abc");
.
综合起来,我们可以看到s
不会悬空,因为它指向一个临时字符串,该字符串将至少在foo
执行期间存在。
构造函数std::string(const char*)
将被用于构造一个临时对象,该对象将在整个函数的生命周期内存在。
因此不会出现任何问题。
第三种情况是当引用绑定到临时对象时。38 如果引用绑定的glvalue是通过以下方式之一获得的,则引用绑定的临时对象或作为引用绑定的子对象的完整对象将在引用的生命周期内保留:
...
然后进一步说明:
此寿命规则的例外情况有:
- 在函数调用([expr.call])中绑定到引用参数的临时对象将持续到包含调用的完整表达式完成。....
这就是我们现在所面临的情况。关于“直到完整表达式完成”的澄清,请参见What is the lifetime of a default argument temporary bound to a reference parameter?。
const char* temp;
void foo(const std::string& s = "abc") {
temp = s.c_str();
}
或者像存储对这个常量引用的引用之类的任何事情,你都应该没问题。