Fro*_*art 27 c++ object-lifetime language-lawyer default-arguments reference-binding
是否可以通过const引用返回默认参数的值,如以下示例所示:
https://coliru.stacked-crooked.com/a/ff76e060a007723b
#include <string>
const std::string& foo(const std::string& s = std::string(""))
{
return s;
}
int main()
{
const std::string& s1 = foo();
std::string s2 = foo();
const std::string& s3 = foo("s");
std::string s4 = foo("s");
}
Run Code Online (Sandbox Code Playgroud)
Bri*_*ian 18
在您的代码中,s1
和s3
都是悬空的引用。s2
而且s4
还可以。
在第一个调用中,std::string
将从默认参数创建的临时空对象创建在包含该调用的表达式的上下文中。因此,它将在的定义的末尾死掉s1
,从而s1
悬而未决。
在第二个调用中,临时std::string
对象用于初始化s2
,然后死亡。
在第三个调用中,字符串文字"s"
用于创建一个临时std::string
对象,该对象也死于的定义的末尾s3
,保持s3
悬空状态。
在第四次调用中,std::string
带有值的临时对象"s"
用于初始化s4
,然后死亡。
参见C ++ 17 [class.temporary] /6.1
绑定到函数调用(8.2.2)中的参考参数的临时对象将一直保留,直到包含该调用的完整表达式完成。
这取决于您随后对字符串的处理方式。
如果您的问题是我的代码正确吗?那是的
[ 示例:声明
Run Code Online (Sandbox Code Playgroud)void point(int = 3, int = 4);
声明一个可以用零,一或两个int类型的参数调用的函数。可以通过以下任何一种方式调用它:
Run Code Online (Sandbox Code Playgroud)point(1,2); point(1); point();
最后两个调用分别等效于
point(1,4)
和point(3,4)
。— 结束示例 ]
因此,您的代码实际上等效于:
const std::string& s1 = foo(std::string(""));
std::string s2 = foo(std::string(""));
Run Code Online (Sandbox Code Playgroud)
您的所有代码都是正确的,但是在任何情况下都没有引用生存期的延长,因为返回类型是引用。
由于您使用临时函数调用函数,因此返回的字符串的生存期不会延长该语句。
const std::string& s1 = foo(std::string("")); // okay
s1; // not okay, s1 is dead. s1 is the temporary.
Run Code Online (Sandbox Code Playgroud)
您的示例s2
可以使用,因为您可以在地块结束之前从临时位置复制(或移动)。s3
与...有同样的问题s1
。