 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Joshua Lehrer Guest
|
Posted: Wed Jan 26, 2005 9:48 am Post subject: lifetime of temporaries and ternary operator |
|
|
Code:
const T& val = test ? T() : T();
what is the type of the result of the ternary operator.
will that temporary be bound to the reference "val" and kept alive for
the lifetime of the reference?
My compiler, edg front-end, says no. If my compiler is right, should
the above even compile?
VC++ (not sure what version) keeps the temporary alive for the lifetime
of the reference.
Which is right?
I've already spent an hour digging through the standard, but I can't
parse the jargon well enough to answer this.
Thanks,
joshua lehrer
factset research systems
NYSE:FDS
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Wed Jan 26, 2005 7:19 pm Post subject: Re: lifetime of temporaries and ternary operator |
|
|
Joshua Lehrer wrote:
| Quote: | Code:
const T& val = test ? T() : T();
what is the type of the result of the ternary operator.
|
Clearly T.
| Quote: | will that temporary be bound to the reference "val" and kept
alive for the lifetime of the reference?
|
A copy of that temporary will be bound to the reference val, and
be kept alive for the lifetime of the reference. The compiler
is free to elide the copy, and I think almost all, if not all,
do.
| Quote: | My compiler, edg front-end, says no. If my compiler is right,
should the above even compile?
VC++ (not sure what version) keeps the temporary alive for the
lifetime of the reference.
Which is right?
|
VC++.
| Quote: | I've already spent an hour digging through the standard, but I
can't parse the jargon well enough to answer this.
|
Well, the text in §5.16 seems fairly clear in this case.
(There's a lot of complicated jargon in that section, but most
of it only applies if the second and the third operand have
different types, which isn't the case here.)
I suspect that the real issue is the lifetime. In fact, neither
of the sub-expressions T() or T() are bound directly to a
reference, and so neither of them gets their lifetime extended.
BUT... they are rvalues; the results of the ?: expression isn't
one of these objects, but an rvalue whose value is the same as
one of these objects. In sum, a copy, which can be elided, and
a (new) temporary, which is bound directly to a const reference,
and whose lifetime must be extended.
At any rate, this seems to me to be the only interpretation
which is consistent with the behavior of rvalues in general.
The text in §5.16 could be clearer about this, if only to insist
on the fact that T must have an accessible copy constructor if
it is to be used as an rvalue result of ?:.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Eric Niebler Guest
|
Posted: Wed Jan 26, 2005 8:52 pm Post subject: Re: lifetime of temporaries and ternary operator |
|
|
Joshua Lehrer wrote:
| Quote: | Code:
const T& val = test ? T() : T();
what is the type of the result of the ternary operator.
|
rvalue of T. See 5.16/6 in the standard.
| Quote: | will that temporary be bound to the reference "val" and kept alive for
the lifetime of the reference?
|
Yes. See 12.2/5.
| Quote: |
My compiler, edg front-end, says no.
|
Sounds like a bug.
--
Eric Niebler
Boost Consulting
www.boost-consulting.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
the.sim@gmail.com Guest
|
Posted: Thu Jan 27, 2005 8:59 pm Post subject: Re: lifetime of temporaries and ternary operator |
|
|
Just FYI, our compiler docs have a special bullet point about this
scenario:
http://h71000.www7.hp.com/commercial/cplus/alpha_doc/ugvimpl.html#temp_lif_sec
<quote>
2.2.18.1 Lifetime of Temporary Objects
Generally the compiler implements destruction of temporary objects at
the end of statements. In certain situations, however, temporary
objects are destroyed at the end of the expression; they do not persist
to the end of the statement. Temporary objects do not persist to the
end of statements in expressions that are:
In operands of built-in conditional operators ( || and && )
In the second or third operand of the ternary operator ( ?: )
Operands to the built-in comma operator ( , )
</quote>
Based on the Standard, it seems like this behavior is incorrect?
Hillel Y. Sims
hsims AT factset.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Sat Jan 29, 2005 4:35 am Post subject: Re: lifetime of temporaries and ternary operator |
|
|
[email]the.sim (AT) gmail (DOT) com[/email] wrote:
| Quote: | quote
2.2.18.1 Lifetime of Temporary Objects
Generally the compiler implements destruction of temporary
objects at the end of statements. In certain situations,
however, temporary objects are destroyed at the end of the
expression; they do not persist to the end of the
statement. Temporary objects do not persist to the end of
statements in expressions that are:
In operands of built-in conditional operators ( || and && ) In
the second or third operand of the ternary operator ( ?: )
Operands to the built-in comma operator ( , )
/quote
Based on the Standard, it seems like this behavior is incorrect?
|
It's not standard conform. On the other hand, the wording used
in the passage you quote suggests that the compiler is using
some pre-standard rules anyway.
Note that historically, ||, && and ?: have caused problems for
compilers, because the constructors may be called
conditionally. Thus, all of the versions of CFront I used
simply punted, and gave the famous "Sorry, not implemented"
message; several other compilers at the time compiled the code
without warning, but systematically called the destructor, even
in the case where the constructor hadn't been called (with
obviously undesirable results).
With a modern compiler, I wouldn't expect too many problems with
the lifetime "to the end of the full expression." The problem
here was the extended lifetime due to the binding to a const
reference. In an expression like cond?T():T(), neither of the
T() are bound to a reference, so there is no reason, a priori,
to extend their lifetime. The total expression, however, is
also a temporary of type T, and in the case in question, it is
bound to a temporary. Technically, this temporary is distinct
from either of the two explict temporaries, but the compiler is
allowed to elide it. What I suspect is happening is that the
compiler is eliding it, but forgetting to extend the lifetime of
the original temporary.
An interesting test would be something like:
T t1 ;
T const& t2 = cond ? t1 : T() ;
with the condition false. Also note that if you do this,
something like:
const_cast< T& >( t2 ).nonConstFunct() ;
later is illegal, *even* if cond were true. A more interesting
case is if T has a mutable member -- even if cond is true,
modifications of the mutable member through t2 may not affect
t1. You might want to try the following code:
! #include <iostream>
! #include <ostream>
! struct T
! {
! T( int i ) : i( i ) {
! std::cout << "T(" << i << ")n" ;
! }
! T( T const& o ) : i( o.i ) {
! std::cout << "T copy, i = " << i << 'n' ;
! }
! T& operator=( T const& o )
! {
! i = o.i ;
! std::cout << "T asgn, i = " << i << 'n' ;
! return *this ;
! }
! ~T()
! {
! std::cout << "T dtor, i = " << i << 'n' ;
! }
! mutable int i ;
! } ;
! void
! f( bool c )
! {
! T t1( 1 ) ;
! T const& t2 = c ? t1 : T( 2 ) ;
! std::cout << t2.i << 'n' ;
! t2.i = 3 ;
! std::cout << t1.i << 'n' ;
! }
! int
! main( int argc, char** )
! {
! f( false ) ;
! f( true ) ;
! return 0 ;
! }
The output should be:
! T(1)
! T(2)
! 2
! 1
! T dtor, i = 3
! T dtor, i = 1
! T(1)
! T copy, i = 1
! 1
! 1
! T dtor, i = 3
! T dtor, i = 1
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|