scope and references to temporaries

R

REH

Though unsafe, is this legal:

const int& foo(const int& i)
{
return i;
}

int j = foo(5);

does the temporary live long enough to be assigned to j?

REH
 
V

Victor Bazarov

REH said:
Though unsafe, is this legal:

const int& foo(const int& i)
{
return i;
}

int j = foo(5);

does the temporary live long enough to be assigned to j?

No. It lives only as long as 'i' inside the 'foo' function scope. As
soon as you return from 'foo', the reference bound to the temporary
goes out of scope, its lifetime ends, and so the temporary itself is
destroyed. The return value reference (initialised from 'i', which is
valid at *that* point) becomes invalid. Trying to initialise 'j' with
it is a crap shoot (undefined behaviour).

So, it's syntactically legal, produces undefined behaviour, and as to
"illegal", I do think it is only illegal in those countries where UB
is outlawed.

V
 
R

REH

Victor Bazarov said:
No. It lives only as long as 'i' inside the 'foo' function scope. As
soon as you return from 'foo', the reference bound to the temporary
goes out of scope, its lifetime ends, and so the temporary itself is
destroyed. The return value reference (initialised from 'i', which is
valid at *that* point) becomes invalid. Trying to initialise 'j' with
it is a crap shoot (undefined behaviour).

So, it's syntactically legal, produces undefined behaviour, and as to
"illegal", I do think it is only illegal in those countries where UB
is outlawed.

Thanks Victor.

REH
 
?

=?ISO-8859-1?Q?Martin_Vejn=E1r?=

Victor said:
No. It lives only as long as 'i' inside the 'foo' function scope. As
soon as you return from 'foo', the reference bound to the temporary
goes out of scope, its lifetime ends, and so the temporary itself is
destroyed. The return value reference (initialised from 'i', which is
valid at *that* point) becomes invalid. Trying to initialise 'j' with
it is a crap shoot (undefined behaviour).

Is that so?

[12.2/5]
[...] A temporary bound to a reference parameter in a function call
(5.2.2) persists until the completion of the full expression containing
the call. [...]

If I read the Standard correctly, the above code doesn't produce a "crap
shoot". Am I missing something?
 
V

Victor Bazarov

Martin said:
Victor said:
No. It lives only as long as 'i' inside the 'foo' function scope. As
soon as you return from 'foo', the reference bound to the
temporary goes out of scope, its lifetime ends, and so the temporary
itself is destroyed. The return value reference (initialised from
'i', which is valid at *that* point) becomes invalid. Trying to
initialise 'j' with it is a crap shoot (undefined behaviour).

Is that so?

[12.2/5]
[...] A temporary bound to a reference parameter in a function
call (5.2.2) persists until the completion of the full expression
containing the call. [...]

If I read the Standard correctly, the above code doesn't produce a
"crap shoot". Am I missing something?

You're right, I must have missed that particular part of this valuable
paragraph. Thank you for the correction.

V
 
B

Bob Hairgrove

Though unsafe, is this legal:

const int& foo(const int& i)
{
return i;
}

int j = foo(5);

Yes.

does the temporary live long enough to be assigned to j?

REH

The standard says that the temporary should live long enough for the
expression enclosing it to finish, but I wouldn't necessarily count on
this behavior unless you are sure that your particular compiler gets
it right.
 
M

Marek Vondrak

The standard says that the temporary should live long enough for the
expression enclosing it to finish, but I wouldn't necessarily count on
this behavior unless you are sure that your particular compiler gets
it right.

Okay. Here is another example:

template <class First, class Second>
class Plus
{
public:
Plus( const First & first, const Second & second ) : first( first ),
second( second ) { }
template <class Third>
Plus< Plus<First, Second>, Third > operator+( const Third & third ) { return
Plus<Plus<First,Second>, Third>( *this, third ); }
const First & first;
const Second & second;
};

class Matrix
{
public:
Plus<Matrix, Matrix> operator+( const Matrix & m ) const { return
Plus<Matrix, Matrix>( *this, m ); }
template <class Type>
Matrix & operator=( const Type & type ) { /* whatever */ return *this; }
};

void test()
{
Matrix a, b, c, d;
a = b + c + d; // [1]
}

Will the temporaries created at [1] live until the whole expression is
finished (ie. until the assignment to 'a' completes)? As far as I know, the
code should be legal since all temporaries created during an evaluation of
an expression (statement) must live until the end of the statement. In fact,
all expression templates based linear algebra labraries rely on this
behaviour.

Thanks
-- Marek
 
R

Ron Natalie

Bob said:
The standard says that the temporary should live long enough for the
expression enclosing it to finish, but I wouldn't necessarily count on
this behavior unless you are sure that your particular compiler gets
it right.

If you're compiler doesn't get this right, it should be discarded.
This is a fairly fundamental concept to the language.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top