c++ - const 참조로 기본 인수 값을 반환해도됩니까?



language-lawyer object-lifetime (2)

아래 예제와 같이 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");
}

https://ffff65535.com


귀하의 코드에서 s1s3 은 매달려있는 참조입니다. s2s4 는 괜찮습니다.

첫 번째 호출에서 기본 인수에서 작성된 임시 빈 std::string 오브젝트는 호출을 포함하는 표현식의 컨텍스트에서 작성됩니다. 따라서 s1 의 정의가 끝나면 s1 매달려있게됩니다.

두 번째 호출에서 임시 std::string 객체를 사용하여 s2 를 초기화 한 다음 죽습니다.

세 번째 호출에서 문자열 리터럴 "s" 는 임시 std::string 오브젝트를 작성하는 데 사용되며 s3 의 정의가 끝나면 s3 매달려있게합니다.

네 번째 호출에서 값이 "s" 임시 std::string 객체를 사용하여 s4 를 초기화 한 다음 죽습니다.

C ++ 17 [class.temporary] /6.1 참조

함수 호출 (8.2.2)에서 참조 매개 변수에 바인드 된 임시 오브젝트는 호출을 포함하는 전체 표현식이 완료 될 때까지 지속됩니다.


나중에 문자열로 무엇을하는지에 따라 다릅니다.

귀하의 질문이 내 코드가 맞다면? 그렇다면 그렇습니다.

[dcl.fct.default]/2

[ : 선언

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

int 유형의 0, 1 또는 2 개의 인수로 호출 할 수있는 함수를 선언합니다. 다음과 같은 방법으로 호출 할 수 있습니다.

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 를 사용한 예는 괜찮습니다. s3s1 과 동일한 문제가 있습니다.





reference-binding