Почему я не могу привязать постоянную ссылку на значение к функции, возвращающей T &&? - PullRequest
0 голосов
/ 04 июля 2018

Я связывал некоторое возвращаемое значение функции со ссылкой на константное значение, но объект был удален до того, как закончился срок действия ссылки на константное значение.

В следующем примере объект Foo уничтожается до окончания срока действия foo:

#include <iostream>
#include <string>

struct Foo
{
    ~Foo()
    {
        std::cout << "Foo destroyed: " << name << std::endl;
    }
    std::string name;
};

Foo&& pass_through(Foo&& foo)
{
    return std::move(foo);
}

int main()
{
    const Foo& foo = pass_through({"some string"});
    std::cout << "before scope end" << std::endl;
}

Вывод:

Foo уничтожено: некоторая строка
до конца области действия

в прямом эфире на колиру: 1

Я думал, что вы можете связать const T& с чем угодно. Является ли плохой практикой возвращать T&& и следует ли возвращать по значению предпочтительнее?

Я наткнулся на это в cpprestsdk здесь:

inline utility::string_t&& to_string_t(std::string &&s) { return std::move(s); }

https://github.com/Microsoft/cpprestsdk/blob/master/Release/include/cpprest/asyncrt_utils.h#L109

Очень запутанно, потому что версия to_string_t для Windows (отправляется макросами препроцессора) возвращается по значению :

_ASYNCRTIMP utility::string_t __cdecl to_string_t(std::string &&s);

Edit: Почему это работает при передаче результата pass_through в функцию, принимающую const Foo&? В этом случае срок службы увеличивается?

1 Ответ

0 голосов
/ 04 июля 2018

Из стандарта:

15,2 Временные объекты

6.9 A temporary object bound to a reference parameter in a function call persists 
    until the completion of the full-expression containing the call.

По сути, это говорит о том, что, поскольку вы передали временный объект, а затем не продлили его время жизни (скажем, переместив его в lvalue), его время жизни длится только до первого ; после вызова pass_through в вашем коде. После этой точки у вас останется foo в качестве свисающей ссылки.

int main()
{
    const Foo& foo = pass_through({"some string"}); // "some string" lifetime ends here
    std::cout << "before scope end" << std::endl;
}

Относительно того, является ли хорошей практикой возвращать референтную ссылку, я полагаю, что эти два ответа уже подробно рассматриваются по этому вопросу:

Должен ли я вернуть опорный параметр rvalue по ссылке rvalue?

Является ли возврат по rvalue ссылкой более эффективным?

...