3

Say I have:

#include <iostream>
#include "boost/optional.hpp"
struct cat
{
    int paw = 4;
};

int main()
{
    boost::optional<cat&> z;
    {
        cat realCat = cat();
        z = realCat;
    }
    std::cout << z->paw << std::endl;
    return 0;
}

In the above, there's no reason to expect a consistent result to be printed, right, as the realCat was released by }? Or does the optional preserve the life of the realCat?

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
Carbon
  • 3,828
  • 3
  • 24
  • 51
  • 2
    You do not understand life extension twice. In your code even regular const or rvalue reference will not extend lifetime. – Slava Dec 26 '17 at 20:01
  • 1
    One of those questions that make me cringe a little but I still upvote because it's a good question well asked, and in fact it's an issue I've admittedly shot myself in the foot with before. I still have a TODO in a code-base to refactor an interface to no longer optimize using `optional` because it's just too dangerous in general-purpose code. – sehe Dec 27 '17 at 03:08

1 Answers1

5

No, it doesn't, your code has undefined behavior when you try to print the value of paw.

The C++ rules for lifetime extension only apply when a temporary object is bound to an rvalue reference or lvalue reference to const, but realCat is not a temporary and binding it to an optional reference doesn't extend it's lifetime.

In any case, these lifetime extension rules don't apply to boost::optional<T&>. The documentation for boost::optional mentions this:

Rvalue references and lvalue references to const have the ability in C++ to extend the life time of a temporary they bind to. Optional references do not have this capability ...

As for std::optional, your program would be ill-formed if you tried to create std::optional<T&>.

[optional.syn]/1

A program that necessitates the instantiation of template optional for a reference type, or for possibly cv-qualified types in_­place_­t or nullopt_­t is ill-formed.

Praetorian
  • 106,671
  • 19
  • 240
  • 328