Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!sunybcs!oswego!news
From: dl@g.g.oswego.edu (Doug Lea)
Newsgroups: comp.lang.c++
Subject: Re: Strings
Message-ID:
Date: 25 Oct 89 10:25:56 GMT
References: <10050@alice.UUCP>
Sender: news@oswego.Oswego.EDU (Network News)
Reply-To: dl@oswego.edu
Distribution: comp
Organization: SUNY Oswego
Lines: 88
In-reply-to: ark@alice.UUCP's message of 24 Oct 89 18:50:31 GMT
I had written...
> > String& addeol(String& s) { s += "\n"; return s; }
>
> > main()
> > {
> > String a, b; //...
> > String c = addeol(a+b);
> > //...
> > }
>
> > which would be illegal if operator+ returned a const String. (Yes,
> > the form of `addeol' is contrived, but not indefensible.)
>
Andy replied...
> The trouble with the example is that the value of a+b is a temporary
> that can be destroyed as soon as addeol() returns. Thus it seems
> to me that it should be OK for a compiler to generate code that
> looks like this:
>
> evaluate a+b into a temporary T
> call addeol(T) and save a reference to the result
> destroy T
> copy the saved result of addeol() into c
>
> In this case, the `saved result' of addeol will have been destroyed
> before copying it, so c will be garbage.
>
> You might say that this argues that the destruction of the temporary
> that holds a+b should be deferred until later. Unfortunately, doing
> that doesn't eliminate the problem, it just makes it less likely.
>
It's hard to be sure. In my (draft) copy of the 2.0 Reference Manual,
section 12.2, it says
The compiler must ensure that a temporary object is destroyed.
There are only two things that can be done with a temporary:
fetch its value (implicitly copying it) to use in some other
expresssion, or bind a reference to it. If the value of a
temporary is fetched, that temporary is dead and can be destroyed
immediately. If a reference is bound to the temporary, the
temporary must not be destroyed until the reference is. This
destruction must take place before exit from the scope in which
the temporary is created.
This statement does not explicitly address what happens with multiple
references: addeol makes a ref of the temp holding a+b, and in turn
binds another ref to it (the return value). The `right' thing to
do is to not kill the temp until the return val reference is destroyed
(after construction into c). Of course, the compiler cannot know this if
addeol is not inline or is an extern, but I assumed that the above rule
requires that a compiler play it safe, and not kill the temp until
all references spawned from expressions involving it die. But I see that
your interpretation could also be right.
As I too weakly implied elsewhere in my last note, I think the temp
rules could be strengthened by generalizing this paragraph via the
simple statement that a temporary (like any normal variable) may be
destroyed only when a compiler can prove that it is no longer useful,
or at the end of the enclosing scope, whichever comes first. This rule
is similar to those used in other languages. The rule requires that if
a temp is involved in any reference-returning member or top-level
function, or a reference is bound to any of its parts, it should live.
It might also be allowed to live if the compiler can prove that it
will be recomputed/reused later in the same block (as may be
discovered via available expression analysis), thus killing off the
recomputation. On the other hand, it might be killed immediately if it
is never used (e.g., the single statement `a+b;'), a possibility
ignored in the above. This restatement would thus cover the current
cases, and also allow the possiblity of a smarter compiler doing
smarter things. (I guess I should add that, as we've gone over before,
a rule like this also helps legitimize and extend the current practice
of not generating X(X&)-based temporaries at all in some situations.)
I should emphasize that the form of addeol is NOT one I recommend.
Oh, I should clarify another remark in my last note: OPERAND evaluation
order is undefined in C++ for `cout << dec(10) << dec(20)'. OPERATOR
evaluation is, of course, left-to-right.
--
Doug Lea, Computer Science Dept., SUNY Oswego, Oswego, NY, 13126 (315)341-2367
email: dl@oswego.edu or dl%oswego.edu@nisc.nyser.net
UUCP :...cornell!devvax!oswego!dl or ...rutgers!sunybcs!oswego!dl