Should we use lifetime extension of a temporary in C++17 and later?

Viewed 165

Since in C++17 it's guaranteed that the temporary created by an expression is stored in a variable assigned to:

#include <iostream>

struct Test
{
    Test()                  { std::cout << "Test()"                 << std::endl;   }
    Test(const Test &rhs)   { std::cout << "Test(const Test &rhs)"  << std::endl;   }
    Test(Test &&rhs)        { std::cout << "Test(Test &&rhs)"       << std::endl;   }

    Test &operator=(Test &&rhs)         { std::cout << "Test &operator=(Test &&rhs)"        << std::endl; return *this; }
    Test &operator=(const Test &rhs)    { std::cout << "Test &operator=(const Test &rhs)"   << std::endl; return *this; }

    ~Test() { std::cout << "~Test()" << std::endl; }
};

Test fun()
{
    return Test{};
}

int main(int argc, char** argv)
{
    auto t = fun();

    return 0;
}

Outputs:

Test()
~Test()

Deleting the assignment operators and the copy and move constructors yields the same result.

Do we still need to extend the lifetime of the temporary ('const auto &t = fun()') for any kind of optimization?

EDIT:

Test &operator=(const Test &&rhs)   { std::cout << "Test &operator=(const Test &rhs)"   << std::endl; return *this; }

Is now:

Test &operator=(const Test &rhs)   { std::cout << "Test &operator=(const Test &rhs)"   << std::endl; return *this; }

EDIT: Question clarified.

EDIT: Removed the 'language-lawyer' tag. This is a genuine question that affects much of my codebase. People normally use lifetime-extension of temporaries for performance reasons. But writing 'const auto &p = ...' is longer than just write 'auto p = ...', which is cleaner and expresses more the desire of the programmer.

1 Answers

Yes, I would still like this to work:

auto const& t = fun();

And for that to work relies upon extending the lifetime of the temporary fun() returns to match the lifetime of t. Otherwise, the Test temporary would be destroyed at end of the expression and I'd immediately have a dangling reference.

You need some way to say "give me whatever" that avoids work if the "whatever" gives you an lvalue. I don't want to do auto t = fun(); where fun() returns a T const&, that's an unnecessary copy. auto const& (or auto&&) avoids the copy in this case, and with lifetime extension works with the prvalue case as well.

Related