26

是否可以通过 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");
}
4

3 回答 3

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) 中绑定到引用参数的临时对象将持续存在,直到包含调用的完整表达式完成为止。

于 2019-11-01T17:52:03.560 回答
8

不安全

一般来说,临时的生命周期不能通过“传递”来进一步延长:第二个引用,从临时绑定的引用初始化,不会影响它的生命周期。

于 2019-11-01T17:47:17.930 回答
5

这取决于你之后对字符串做什么。

如果您的问题是我的代码是否正确?那么是的。

来自[dcl.fct.default]/2

[示例:声明

void point(int = 3, int = 4);

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

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(""));

您的所有代码都是正确的,但在任何这些情况下都没有引用生命周期延长,因为返回类型是引用。

由于您使用临时函数调用函数,因此返回字符串的生命周期不会延长语句。

const std::string& s1 = foo(std::string("")); // okay

s1; // not okay, s1 is dead. s1 is the temporary.

您的示例没问题,s2因为您在状态结束之前从临时文件中复制(或移动)。s3有同样的问题s1

于 2019-11-01T17:53:45.813 回答