是否可以通过const引用返回默认参数的值?

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

在您的代码中,s1s3都是悬空的引用。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)中的参考参数的临时对象将一直保留,直到包含该调用的完整表达式完成。

  • @ Peter-ReinstateMonica参见[expr.call] / 4,“ ...每个参数的初始化和销毁​​在调用函数的上下文中发生。...” (2认同)

Obl*_*ica 8

这是不安全的

通常,不能通过“传递”来进一步延长临时项的生存期:从临时项所绑定到的引用初始化的第二个引用不影响其生存期。


Gui*_*cot 5

这取决于您随后对字符串的处理方式。

如果您的问题是我的代码正确吗?那是的

[dcl.fct.default] / 2开始

[ 示例:声明

void point(int = 3, int = 4);
Run Code Online (Sandbox Code Playgroud)

声明一个可以用零,一或两个int类型的参数调用的函数。可以通过以下任何一种方式调用它:

point(1,2);  point(1);  point();
Run Code Online (Sandbox Code Playgroud)

最后两个调用分别等效于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