From: jss@lucid.com (Jerry Schwarz)
Subject: Re: destruction of temporaries
Reply-To: jss@lucid.com (Jerry Schwarz)
Organization: Lucid, Inc.
Date: Mon, 17 Aug 92 21:15:08 GMT

In article <23466@alice.att.com>, ark@alice.att.com (Andrew Koenig) writes:
|> This treatment [end of statement] has two significant disadvantages:
|> 
|> 	1. If I break a statement up into several, it may
|> 	   quietly change its meaning.  Thus, for example, if
|> 	   String::operator const char*() exists, and s and t are
|> 	   of class String, then
|> 
|> 		printf("%s\n", (const char*)(s+t));
|> 	
|> 	   might work but
|> 
|> 		const char* r = s + t;
|> 		printf("%s\n", r);
|> 	   
|> 	   might not.

And I feel that I should be able to add a { } around an expression
statement without changing its meaning.  In other words I ought
to be able to further transform the above to

		const char* r = "" ;
		if ( 1 ) { r = s+t ; } 
		printf("%s\n", r) 


Even "end of block" (the latest anyone has proposed) makes
this example undefined.

Absent garbage collection, the existence of temporaries and member
functions that return pointers to their internals cannot be ignored
by programmers. While it is unfortunate that breaking up of a statement
in an ill choosen way can have consequences.  It seems even more
unfortunate to me if I can't write the original printf.  Note that 
although early destruction of temporaries makes the first example undefined,
it still might appear to work on many implementations. 

Early destruction makes many useful idioms impossible. 
The above example is inherently suspect because it uses 
member function returning a pointer to its internals.  But consider

	class Dialogbox : public istream { ... } ;
	Dialogbox("enter address(in hex)") >> hex >> n ;

There is nothing suspect here unless you consider it suspicious
to pass a temporary to a function expecting a reference

|> 
|> 	2. It is a real pain to implement for statements that
|> 	   generate temporaries inside conditionals.  


Yes, it requires more effort on the part of compiler vendors to get it 
right,  but a lot less than many other features of C++.  

	   ...
|>      .  There are cases where this can add substantially
|> 	   to execution time.

It is possible to construct examples where the bookkeeping is a significant
overhead. But I don't believe this is a substantial problem in practice. 

|>         Moreover, it greately complicates the
|> 	   implementation of exception handling, because it makes it
|> 	   impossible to have a static map from program counter value
|> 	   to offsets of statics to destroy.

It isn't quite true that it becomes impossible to have a static map.
The cost of doing so is duplicated code.  For example

	fred(x>0?f(p+q):r) 

can to be transformed to (approximately) 

	if ( x>0 ) { fred(f(p+q)) ;
	else fred(r) ;

An alternative implementation requires flags in some cases to
determine which temps have been constructed, and the static
data structure would have to indicate this. The normal case where there
is no flag would require no extra overheads.

Compared to the effort to implement exceptions in the first place,
the extra effort required to get the lifetime of temporaries correct
doesn't seem inordinate.

  -- Jerry Schwarz




For these reasons I believe "end of statement" (or more properly
"end of outermost expression") is the best answer for lifetime
of temporaries.

   -- Jerry Schwarz



Newsgroups: comp.lang.c++,comp.sys.mac.programmer