LINUX.ORG.RU

История изменений

Исправление LamerOk, (текущая версия) :

Со стандарта:

15.2
Temporary objects
...
6 The third context is when a reference is bound to a temporary. The temporary to which the reference is
bound or the temporary that is the complete object of a subobject to which the reference is bound persists
for the lifetime of the reference except:
—
(6.1)
A temporary object bound to a reference parameter in a function call (8.2.2) persists until the completion
of the full-expression containing the call.
—
(6.2)
The lifetime of a temporary bound to the returned value in a function return statement (9.6.3) is not
extended; the temporary is destroyed at the end of the full-expression in the return statement.
...

Конкретно в ОП-посте исключение п. 6.1. Для возвращаемых значений это работает:

9.6.3
The return statement
...

3
The copy-initialization of the result of the call is sequenced before the destruction of temporaries at the end
of the full-expression established by the operand of the return statement, which, in turn, is sequenced before
the destruction of local variables (9.6) of the block enclosing the return statement.
user@computer:$ cat cpp_reference.cpp 
#include <optional>
#include <iostream>

struct T
{
    int i;
    T(int i):i(i){};
    ~T(){i = 42;};
};


T f1()
{
    return T(7);
}

std::optional<T> f2()
{
    return T(13);
}

int main()
{
    const T &t1 = f1();
    std::cout << "Print: " << t1.i << "\n";

    std::optional<T> t2;
    // UB: std::cout << "Print: " << t2->i << "\n";

    t2 = f2();
    std::cout << "Print: " << t2->i << "\n";

    return 0;
}
user@computer:$ 
user@computer:$ g++ -std=c++23 -O0 -Wall -Werror  cpp_reference.cpp -o temp_reference
user@computer:$ ./temp_reference 
Print: 7
Print: 13
user@computer:$

Исправление LamerOk, :

Со стандарта:

15.2
Temporary objects
...
6 The third context is when a reference is bound to a temporary.116 The temporary to which the reference is
bound or the temporary that is the complete object of a subobject to which the reference is bound persists
for the lifetime of the reference except:
—
(6.1)
A temporary object bound to a reference parameter in a function call (8.2.2) persists until the completion
of the full-expression containing the call.
—
(6.2)
The lifetime of a temporary bound to the returned value in a function return statement (9.6.3) is not
extended; the temporary is destroyed at the end of the full-expression in the return statement.
...

Конкретно в ОП-посте исключение п. 6.1. Для возвращаемых значений это работает:

9.6.3
The return statement
...

3
The copy-initialization of the result of the call is sequenced before the destruction of temporaries at the end
of the full-expression established by the operand of the return statement, which, in turn, is sequenced before
the destruction of local variables (9.6) of the block enclosing the return statement.
user@computer:$ cat cpp_reference.cpp 
#include <optional>
#include <iostream>

struct T
{
    int i;
    T(int i):i(i){};
    ~T(){i = 42;};
};


T f1()
{
    return T(7);
}

std::optional<T> f2()
{
    return T(13);
}

int main()
{
    const T &t1 = f1();
    std::cout << "Print: " << t1.i << "\n";

    std::optional<T> t2;
    // UB: std::cout << "Print: " << t2->i << "\n";

    t2 = f2();
    std::cout << "Print: " << t2->i << "\n";

    return 0;
}
user@computer:$ 
user@computer:$ g++ -std=c++23 -O0 -Wall -Werror  cpp_reference.cpp -o temp_reference
user@computer:$ ./temp_reference 
Print: 7
Print: 13
user@computer:$

Исходная версия LamerOk, :

Со стандарта:

15.2
Temporary objects
...
6 The third context is when a reference is bound to a temporary.116 The temporary to which the reference is
bound or the temporary that is the complete object of a subobject to which the reference is bound persists
for the lifetime of the reference except:
—
(6.1)
A temporary object bound to a reference parameter in a function call (8.2.2) persists until the completion
of the full-expression containing the call.
—
(6.2)
The lifetime of a temporary bound to the returned value in a function return statement (9.6.3) is not
extended; the temporary is destroyed at the end of the full-expression in the return statement.

Конкретно в ОП-посте исключение п. 6.1. Для возвращаемых значений это работает:

9.6.3
The return statement
...

3
The copy-initialization of the result of the call is sequenced before the destruction of temporaries at the end
of the full-expression established by the operand of the return statement, which, in turn, is sequenced before
the destruction of local variables (9.6) of the block enclosing the return statement.
user@computer:$ cat cpp_reference.cpp 
#include <optional>
#include <iostream>

struct T
{
    int i;
    T(int i):i(i){};
    ~T(){i = 42;};
};


T f1()
{
    return T(7);
}

std::optional<T> f2()
{
    return T(13);
}

int main()
{
    const T &t1 = f1();
    std::cout << "Print: " << t1.i << "\n";

    std::optional<T> t2;
    // UB: std::cout << "Print: " << t2->i << "\n";

    t2 = f2();
    std::cout << "Print: " << t2->i << "\n";

    return 0;
}
user@computer:$ 
user@computer:$ g++ -std=c++23 -O0 -Wall -Werror  cpp_reference.cpp -o temp_reference
user@computer:$ ./temp_reference 
Print: 7
Print: 13
user@computer:$